MySQL -GROUP之前的ORDER BY对结果没有影响

lpwwtiir  于 2023-02-28  发布在  Mysql
关注(0)|答案(1)|浏览(193)

我在这个问题上所做的所有研究表明,先前排序的结果集是控制GROUP BY行为的方法,但它在这里根本不起作用。
我正在编写代码来清除重复值,并且需要仅在存在重复值时保存每个campaign_main_ref_id的最高item_state_c ID。正如您所看到的,只有campaign 92和94具有多个项目。问题是,无论我执行什么操作,都无法获得GROUP BY结果来返回基于最高item_state_c ID的ID。(DESC)item_state_c的排序顺序。为清楚起见,下面是源表:

问题是,它永远不会基于item_state_c = 3返回活动92的ID 45893。如您所见,我在CTE引用中按item_state_c DESC排序-但GROUP BY忽略了这一点。
那么,如何在此场景中使用GROUP BY,以便根据项目状态为活动92选择45893呢?
下面是生成表(campaign_items)并尝试分组和利用之前排序(不起作用-不知道为什么)的代码:

WITH
frontload_array AS
(
  SELECT jt.ID 
  FROM JSON_TABLE('[182723,182722,182721,178216,2]', '$[*]' COLUMNS(ID int PATH '$')) AS jt
),
campaign_items AS
(
    SELECT ci.ID, ci.campaign_main_ref_id, ci.item_state_c
    FROM campaign_item ci
    WHERE ci.item_object_type_sc = 4
    AND ci.item_object_subtype_sc = 1
    AND ci.item_object_ref_id IN (SELECT ID FROM frontload_array)
    ORDER BY ci.item_state_c DESC
),
campaign_duplicates AS
(
    SELECT ci.ID, ci.item_state_c, ci.campaign_main_ref_id
    FROM campaign_items ci
    GROUP BY ci.campaign_main_ref_id
    HAVING COUNT(ci.campaign_main_ref_id) > 1    
)
SELECT * FROM campaign_duplicates;

下面是campaign_duplicates的结果:

问题是它没有利用这个GROUP中以前的ORDER BY,这是我的问题的一致"解决方案"-但它根本不起作用(如您所见)。
我所需要的是一个SQL调用,为每个有多个项目的活动返回item_state_c最高的ID,我不知道没有GROUP BY怎么做,而且根据我的理解,ORDER BY只对GROUP BY之后的数据进行排序,所以我不知所措;特别是在引用表I GROUP中设置顺序似乎不会产生任何影响。我只是不明白GROUP BY如何确定它所选择的ID,因为它是一个中间ID号。
任何帮助都将不胜感激。

w46czmvw

w46czmvw1#

可以忽略在子查询中执行ORDER BY。
https://dev.mysql.com/doc/refman/8.0/en/derived-table-optimization.html
如果以下条件全部为真,则优化程序会将派生表或视图引用中的ORDER BY子句传播到外部查询块:

  • 外部查询不进行分组或聚合。
  • 外部查询不指定DISTINCT、HAVING或ORDER BY。
  • 外部查询将此派生表或视图引用作为FROM子句中的唯一源。

否则,优化程序将忽略ORDER BY子句。
在您的示例中,您要进行聚合,因此ORDER BY将被删除。
由于您使用的显然是MySQL 8.0,因此应该使用窗口函数:

WITH
frontload_array AS
(
  SELECT jt.ID 
  FROM JSON_TABLE('[182723,182722,182721,178216,2]', '$[*]' COLUMNS(ID int PATH '$')) AS jt
),
campaign_items AS
(
    SELECT ci.ID, ci.campaign_main_ref_id, ci.item_state_c,
      ROW_NUMBER() OVER (PARTITION BY ci.campaign_main_ref_id ORDER BY ci.item_state_c DESC) AS rownum
    FROM campaign_item ci
    WHERE ci.item_object_type_sc = 4
    AND ci.item_object_subtype_sc = 1
    AND ci.item_object_ref_id IN (SELECT ID FROM frontload_array)
),
SELECT ci.ID, ci.item_state_c, ci.campaign_main_ref_id
FROM campaign_items ci
WHERE ci.rownum = 1;

相关问题