2011-11-30 55 views
3

我需要为一个表创建一个select查询,合并每个组在'Number'列上的行,以获得具有所有可用但最新(按ID)列的单个行。MySQL合并行值为单行

这里就是我的意思是,我需要一台这样的:

ID | Number | Date 1 | Date 2 | Date 3 | 
---------------------------------------------------- 
1 | 1 | 2011-10-01 | NULL | NULL | 
2 | 1 | NULL | 2011-10-25 | NULL | 
3 | 1 | NULL | NULL | 2011-11-13 | 
4 | 1 | 2011-10-03 | NULL | 2011-11-10 | 
5 | 2 | NULL | NULL | 2012-01-01 | 
6 | 2 | 2012-03-11 | NULL | NULL | 

,并返回本(ID列是无关的上述ID列):

ID | Number | Date 1 | Date 2 | Date 3 | 
---------------------------------------------------- 
1 | 1 | 2011-10-03 | 2011-10-25 | 2011-11-10 | 
2 | 2 | 2012-03-11 | NULL | 2012-01-01 | 

所以对于每个组中的所有行通过'Number'列,我需要组中所有行的所有可用列值,但只需要每列的最新值。最新值由列中值的最高值'ID'确定。 (如果组中的任何一行中没有值,则使用Null值)。

谢谢

回答

1

感谢大家的建议。不幸的是,我一直无法为我解决当前的任何问题。 不幸的是,我不能依赖聚合函数的日期使用,因为它们可能不是最大值或最小值。 每个日期列使用子查询是非常聪明的,但我无法使查询运行速度足以满足我的使用需求。 (它需要几乎立即运行,但是尽管正确配置索引,但是正在谈论一个相当长的时间。)

我想出的解决方案是创建一个带有结构的新表以保存结果,然后通过多个触发器保持该表的最新状态。有问题的实际表格会定期更新,插入到表格中应该允许我使用触发器保持单独的表格,从而为我提供所需的信息。

1

您可以使用子查询来选择不同的数字。然后,对于每个数字,您可以查看另一个子查询中的各个列。子查询将查找具有最高ID的行,其中该特定列不为空。

select yt.Number 
,  (
     select top 1 [Date 1] 
     from YourTable d1 
     where d1.Number = yt.Number 
       and d1.[Date 1] is not null 
     order by 
       d1.ID desc 
     ) as [Date 1] 
,  (
     select top 1 [Date 2] 
     from YourTable d2 
     where d2.Number = yt.Number 
       and d2.[Date 2] is not null 
     order by 
       d1.ID desc 
     ) as [Date 2] 
,  ... 
from (
     select distinct Number 
     from YourTable 
     ) as yt 
+0

哇,这很快! 我担心有很多子查询,我将这样做的实际表格有超过200,000行,每组最多20-30行。 – JohnHenry

+0

可以进一步对其进行优化,但先尝试一下吗? 200k行对于SQL Server不是很多 – Andomar

0

这deepends你的数据,你可以使用聚合函数了。*

如果您的数据总是在其他行空值,聚合函数会忽略它们。这意味着您可以使用GROUP BY获取单个行。

SELECT ID, Number, MAX(Date1), MAX(Date2), MAX(Date3) 
FROM MyTable 
GROUP BY ID, Number 

* 注意:此,如果你知道你总是希望当然值MAX(或MIN)才有效。在你的问题中,你声明你想要一个ID最高的人,所以我的解决方案可能无法工作。

0

您正在查找的“ID”编号显示为简单顺序,表示结果集的最终“行”编号(因为您指示的编号与原始编号列没有关系)。因此,考虑到Cylindric以前的答案,只是扩大一点...

select 
     @FinalRow := @FinalRow +1 as ID, 
     PreQuery.* 
    from 
     (SELECT 
       Number, 
       MAX(Date1), 
       MAX(Date2), 
       MAX(Date3) 
      FROM 
       MyTable 
      GROUP BY 
       Number 
      ORDER BY 
       Number) PreQuery, 
     (select @FinalRow := 0) SQLVars