2011-10-22 72 views
4

我有以下数据MAX聚合

GROUP_ID INDEX 
    NULL  1 
    1  2 
    NULL  3 
    1  4 
    NULL  5 
    2  6 
    2  7 

我想要的是得到一个包含字段:

  • 如果GROUP_ID IS NOT NULL,该组中最小的指数
  • 如果group_id为NULL,则来自该行的索引

以上示例的结果数据集为:

GROUP_ID INDEX GROUP_INDEX_MIN 
    NULL  1   1 
    1  2   2 
    NULL  3   3 
    1  4   2 
    NULL  5   5 
    2  6   6 
    2  7   6 

在Oracle我会用(CASE WHEN group_id IS NOT NULL THEN MIN(index) OVER (PARTITION BY group_id) ELSE group_id END)解决这个问题,但由于MySQL不支持,我真的不知道如何进行:)我可以通过为每个检索最小值的子查询解决这个小组,然后离开加入,但我认为必须有一个更优雅的解决方案。

如果您需要更多信息,请询问。 谢谢。

+0

在你的答案中,表格包含冗余的GROUP_INDEX_MIN重复。我建议修改这个设计。也许两个独立的查询会更好。 – Mikhail

回答

4

只需创建代表分钟Group_index_min(薄荷),然后加入到它的内嵌视图,做GROUP_ID和最小

SELECT t.group_id, 
     t.index, 
     Coalesce(t.group_id, minTgroup_index_min) group_index_min 
FROM yourtable t 
     LEFT JOIN (SELECT group_id, 
         MIN(index) group_index_min 
        FROM yourtable 
        GROUP BY 
         group_id) minT 
     ON t.group_id = minT.group_id 
+0

其实我已经做了类似的事情,我想知道是否有一个解决方案,不包括两个查询主表? – phil

+0

不,不,如果你的索引是好的,性能应该很好 –

+0

@ConradFrix:它应该是'GROUP BY group_id',对吧? –

0

之间的聚结,我想我找到了解决办法:

SELECT a.group_id, a.index, (CASE WHEN a.group_id IS NOT NULL THEN a.group_index_min ELSE a.index END) group_index_min 
FROM (
SELECT 
    p.group_id, p.index, 
    (CASE WHEN @group <> IFNULL(p.group_id, 0) THEN @n := p.index ELSE @n := @n END) group_index_min, 
    @group := IFNULL(p.group_id, 0) 
FROM 
    temp p 
ORDER BY p.group_id, p.index 
) A 
ORDER BY 
    (CASE WHEN a.group_id IS NOT NULL THEN a.group_index_min ELSE a.index END) 

这适用于我的示例,按其索引(如果它们不属于某个组)或按组索引(如果它们确实属于某个组)归类值,则适用于我的示例。现在尝试应用到我的真实表格/数据:)

如果有人愿意查看并说出它是否包含一些MySQL不必要的东西,我会非常感激。正如我所说,我不是MySQL专家,所以我不确定这是否是解决此问题的最佳方法。

+0

@康拉德的答案更简单。 –

+0

虽然我同意@ypercube,但至少可以改进您的解决方案*以使其更加简单。这里是我的尝试: 'SELECT p。\ index \', (CASE WHEN @group = p.group_id THEN @n ELSE @n:= p。\ index \'END)group_index_min, ( @group:= p.group_id)group_id FROM temp p ORDER BY p.group_id,p。\ index \''。正如你所看到的,'group_id'列必须重新定位到列列表的末尾。如果这对您很重要,您可以从结果集中进行选择,并按要求的顺序放置这些列。 –

1

万一你只想找到每个组的最低INDEX值,而无需输出整个表,因此重复非NULL GROUP_ID S,你可以尝试以下查询:

SELECT 
    GROUP_ID, 
    MIN(`INDEX`) AS GROUP_INDEX_MIN 
FROM atable 
GROUP BY 
    GROUP_ID, 
    CASE WHEN GROUP_ID IS NULL THEN `INDEX` ELSE GROUP_ID END 

它应该返回是这样的:

GROUP_ID GROUP_INDEX_MIN 
-------- --------------- 
NULL  1 
NULL  3 
NULL  5 
1   2 
2   6 

也就是说,正如我所说,非NULL值GROUP_ID的重复被抑制。

+0

感谢您的努力,但我必须输出整个表格而不排除任何行。 – phil

0

一个尝试:

SELECT 
    GROUP_ID 
    , `INDEX` 
    , COALESCE((SELECT MIN(ti.GROUP_INDEX_MIN) 
       FROM TableX AS ti 
       WHERE ti.GROUP_ID = t.GROUP_ID 
      ) 
      , t.GROUP_INDEX_MIN 
      ) AS GROUP_INDEX_MIN 
FROM 
    TableX AS t 
ORDER BY 
    GROUP_INDEX_MIN 
0

的加入“PreQuery”是所有组包括空条目来完成的。所以,甚至不需要左连接。然而,应用“CASE/WHEN”仍然会看到来自原始源的“NULL”条目,并以此为基础来获取MinIndex(当不为null时),或者仅使用它自己的索引位置(当它为null时)

select 
     YT.Group_ID, 
     YT.`Index`, 
     CASE WHEN YT.GROUP_ID IS NULL 
     THEN YT.`Index` 
     ELSE YT2.MinIndex END as Group_Index_Min 
    from 
     YourTable YT 
     JOIN (select YT2.Group_ID, 
         MIN(YT2.`Index`) MinIndex 
        from YourTable YT2 
        group by YT2.Group_ID) YTMin 
      on YT.Group_ID = YTMin.Group_ID