2011-11-30 63 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