具有多列group by和where子句的每列的最新值

时间:2013-05-15 19:13:53

标签: mysql sql group-by indexing where-clause

鉴于这200万+条目表,ID自动递增和index1(MainId,SubID,Column1) 索引2(MainId,子ID,列2):

ID  MainID  SubID  Column1    Column2 
--------------------------------------
1     1       A   1A_data_1           
2     1       A              1A_data_2
3     2       B   2B_data_1           
4     2       B              2B_data_2
5     1       A   ignore_me             
6     1       A              1A_data_3

我可以使用以下索引获取包含所需列值的行ID:

Select max(ID) 
From table where column1 is not null and column1 <>'ignore_me'
Group By MainID,SubID

Select max(id) 
From table where column2 is not null and column2 <>'ignore_me'
Group By MainID,SubID

但是,我不能做的是找到一种有效的方法来将这些连接到MainID,SubID组以获得这些结果:

MainID  SubID  Column1    Column2
--------------------------------
  1       A   1A_data_1  1A_data_3
  2       B   2B_data_1  2B_data_2

我尝试了很多不同的方法,但没有什么不会永远消失的。我需要另一个索引吗?我觉得我忽略了一些简单的事情,因为通过查询的团队非常快。有人能指出我正确的方向吗?

1 个答案:

答案 0 :(得分:1)

您可以使用条件聚合计算单个查询中的两个ID:

SELECT
  MainID,
  SubID,
  MAX(CASE WHEN Column1 <> 'ignore_me' THEN ID END) AS ID1,
  MAX(CASE WHEN Column2 <> 'ignore_me' THEN ID END) AS ID2
FROM atable
GROUP BY
  MainID,
  SubID
;

您还可以在WHEN条件中明确添加AND ColumnN IS NOT NULL,但这不是必需的,无论如何都会忽略NULL值。

现在,您只需将上述子查询的两个左连接作为派生表执行:

SELECT
  tm.MainID,
  tm.SubID,
  t1.Column1,
  t2.Column2
FROM (
  SELECT
    MainID,
    SubID,
    MAX(CASE WHEN Column1 <> 'ignore_me' THEN ID END) AS ID1,
    MAX(CASE WHEN Column2 <> 'ignore_me' THEN ID END) AS ID2
  FROM atable
  GROUP BY
    MainID,
    SubID
) tm
  LEFT JOIN atable t1 ON tm.ID1 = t1.ID
  LEFT JOIN atable t2 ON tm.ID2 = t2.ID
;

更新(转换为视图,回答评论)

到目前为止,我只能看到一个对VIEW友好的替代方案:

SELECT
  MainID,
  SubID,
  (
    SELECT Column1
    FROM atable
    WHERE MainID = t.MainID
      AND SubID  = t.SubID
      AND Column1 <> 'ignore_me'
    ORDER BY ID DESC
    LIMIT 1
  ) AS ID1,
  (
    SELECT Column2
    FROM atable
    WHERE MainID = t.MainID
      AND SubID  = t.SubID
      AND Column2 <> 'ignore_me'
    ORDER BY ID DESC
    LIMIT 1
  ) AS ID2
FROM atable t
GROUP BY
  MainID,
  SubID
;

此查询可能比前​​一个查询慢:它使用两个相关的子查询,我不确定具有相关子查询的查询(或特别是视图)在MySQL中是否有效。正确的索引可能会有所帮助。一般来说,您可能需要自己测试一下。