收缩GROUP BY结果

时间:2015-09-24 18:32:55

标签: mysql sql

我不确定GROUP BY是否是找到我要找的东西的正确方法。 假设你有一个像

这样的表
UID     ID     VERSION  A       B       C
------------------------------------------------
1       1       3       'a'     NULL    NULL
2       1       2       NULL    'b'     NULL
3       1       1       NULL    NULL    'c'
4       2       3       NULL    'dd'    NULL
5       2       2       NULL    'd'     'e'
6       2       1       'f'     NULL    NULL

现在,我想通过IDVERSIONDESC)对组进行分组/选择来选择某种缩小的行,然后仅使用第一个匹配的{{1} } cell。

结果应为(NOT NULL未指定)

VERSION

或使用类似ID VERSION A B C ----------------------------------------- 1 3 'a' 'b' 'c' 2 3 'f' 'dd' 'e'

的s.th的特定VERSION
WHERE version <= 2

我甚至不确定这样的版本化是否有意义。我在考虑具有大内容的单元格,其中只有一些列经常被更改,并且在每次更改时复制其他未更改的列将是一个巨大的开销。

2 个答案:

答案 0 :(得分:5)

除了GROUP BY,我无法想到任何其他事情。

为什么不试试这个?

SELECT id, MAX(version) as version,
    SUBSTRING_INDEX(GROUP_CONCAT(A ORDER BY version DESC ),',',1)  as A,
    SUBSTRING_INDEX(GROUP_CONCAT(B ORDER BY version DESC ),',',1)  as B,
    SUBSTRING_INDEX(GROUP_CONCAT(C ORDER BY version DESC ),',',1)  as C
FROM table WHERE version <= 2
GROUP BY id;

所以这个 -

  1. 基本上分别对As,Bs和Cs的所有值进行分组(按版本降序排序)
  2. 然后获取每个的第一个值(在第一个逗号之前)
  3. 只要您没有达到GROUP_CONCAT长度限制约束

    ,这应该可以正常工作

答案 1 :(得分:2)

为了完整性,这里使用分析函数(优雅地解决长组问题) Oracle 数据库的解决方案

 with lst as (
 select   ID, VERSION, A, B, C,
 last_value(A ignore nulls) over (partition by ID order by VERSION) as LAST_A,
 last_value(B ignore nulls) over (partition by ID order by VERSION) as LAST_B,
 last_value(C ignore nulls) over (partition by ID order by VERSION) as LAST_C,
 row_number() over (partition by ID order by VERSION DESC) as rn
 from tst
 WHERE version <= 2 /* comment out to get all versions */
 )
 select 
   ID, VERSION, LAST_A as A, LAST_B as B, LAST_C as C
 from lst 
 where rn = 1
 order by id;