PHP中获取同时存在于两种类型的排序结果需求及代码求助
筛选同时存在于两种类型的编号的SQL查询优化
先明确你的核心需求:只保留那些同时属于两种类型(对应你代码里的product_id 8和7)的编号,排除仅属于单一类型的编号。
原代码的问题
你当前的SQL里,子查询T和W是完全相同的——都同时包含了product_id 8和7的记录,然后通过T.number = W.number做连接,这本质上是让每个编号和自身匹配,根本无法区分该编号是否同时存在于两种类型中,自然会保留仅属于单一类型的编号。
解决方案
根据你的需求,我提供两种针对性的方案,你可以根据实际场景选择:
方案1:先筛选符合条件的记录,再分组筛选跨类型的编号
如果你的需求是所有满足数量阈值、且同时属于两种类型的编号(不限制每个类型的数量上限),可以用这个方案:
SELECT number, -- 分别获取两种类型下的数量总和 MAX(CASE WHEN product_id = 8 THEN MOST_FREQUENT END) AS super_type_freq, MAX(CASE WHEN product_id = 7 THEN MOST_FREQUENT END) AS box_type_freq, MAX(MOST_FREQUENT) AS max_val FROM ( -- 先获取每个类型+编号组合的数量总和,筛选满足阈值的记录 SELECT product_id, number, SUM(quantity) AS MOST_FREQUENT FROM bill_details WHERE date_status = 1 AND product_id IN (8, 7) GROUP BY product_id, number HAVING SUM(quantity) >= $d_limit_3 ) AS sub_query -- 按编号分组,筛选出同时存在于两种类型的编号 GROUP BY number HAVING COUNT(DISTINCT product_id) = 2 -- 保持你原来的排序逻辑 ORDER BY CONCAT(LPAD(max_val, 100, '0'), number) DESC, number, super_type_freq, box_type_freq;
方案2:分别获取两种类型的TOP500,再取交集
如果你的需求是先从每种类型里取前500个高频编号,再保留同时出现在两个TOP列表里的编号,这个方案更贴合你原代码里的LIMIT 500逻辑:
SELECT T.number, T.MOST_FREQUENT AS super_type_freq, W.MOST_FREQUENT AS box_type_freq, GREATEST(T.MOST_FREQUENT, W.MOST_FREQUENT) AS max_val FROM ( -- 单独获取super类型(product_id=8)的前500个符合条件的编号 SELECT product_id, number, SUM(quantity) AS MOST_FREQUENT FROM bill_details WHERE date_status = 1 AND product_id = 8 GROUP BY product_id, number HAVING SUM(quantity) >= $d_limit_3 ORDER BY SUM(quantity) DESC LIMIT 500 ) AS T -- 用INNER JOIN取两个类型TOP列表的交集,只保留同时存在的编号 INNER JOIN ( -- 单独获取box类型(product_id=7)的前500个符合条件的编号 SELECT product_id, number, SUM(quantity) AS MOST_FREQUENT FROM bill_details WHERE date_status = 1 AND product_id = 7 GROUP BY product_id, number HAVING SUM(quantity) >= $d_limit_3 ORDER BY SUM(quantity) DESC LIMIT 500 ) AS W ON T.number = W.number -- 保持原排序逻辑 ORDER BY CONCAT(LPAD(max_val, 100, '0'), T.number) DESC, T.number, super_type_freq, box_type_freq;
关键逻辑说明
- 两种方案都通过筛选同时存在于两个product_id分组的编号来实现你的需求,排除仅属于单一类型的记录。
- 方案2的
INNER JOIN是取交集的核心:只有同时出现在两个子查询结果里的编号才会被保留,完美匹配你要排除单一类型编号的要求。
内容的提问来源于stack exchange,提问作者user_777
相关产品推荐
相关产品推荐

