2017年10月31日 星期二

SQL GROUP BY MAX() 取所有欄位

假設有一個資料表如下
| Id | Message | GroupId | Date |
|-------------------------------|
| 1  | Hello   | 1       | 1:00 |
| 2  | Hello   | 1       | 1:01 |
| 3  | Hey     | 2       | 2:00 |
| 4  | Dude    | 3       | 3:00 |
| 5  | Dude    | 3       | 3:01 |
但我想撈取的結果如下
| Id | Message | GroupId | Date |
|-------------------------------|
| 1  | Hello   | 1       | 1:00 |
| 3  | Hey     | 2       | 2:00 |
| 4  | Dude    | 3       | 3:00 |
也就是想要Message不重複,然後Date取最小值得的,一般會這樣下SQL
SELECT Message,MIN(Date) FROM GROUP BY Message

來取得這樣的結果,但是我想取到所有的欄位該如何下SQL呢

方法一: 使用EF LINQ
var result = data.GroupBy(item => item.GroupId)
                 .Select(grouping => grouping.FirstOrDefault())
                 .OrderByDescending(item => item.Date)
                 .ToList();

或
var result = data.GroupBy(item => item.GroupId)
                 .SelectMany(grouping => grouping.Take(1))
                 .OrderByDescending(item => item.Date)
                 .ToList();

若想使用Order by
var result = data.GroupBy(item => item.GroupId)
                 .SelectMany(grouping => grouping.OrderBy(item => item.Date).Take(1))
                 .OrderByDescending(item => item.Date)
                 .ToList();
方法二: 使用SQL CTE
WITH CTE AS
(
    SELECT GroupId, MIN(Date) as MinDate
    FROM table
    GROUP BY GroupId
)
SELECT
    T.*
FROM table AS T
JOIN CTE AS C on C.GroupId = T.GroupId AND C.MinDate=T.Date

沒有留言:

張貼留言