簡體   English   中英

在 MSSQL 中按一列排序

[英]Order By One One Column in MSSQL

我有以下 SQL 表:

[日歷]

[CalendarId]
[Name]

樣本數據:

CalendarId  ResourceKey    Name
1           1              tk1-Room1
2           2              tk1-Room2
3           3              tk1-noentries

[日歷條目]

[CalendarId]
[CalendarEntryId]
[Start]
[End]

樣本數據:

CalendarId  Start                            End
1           2019-11-18 16:00:00.0000000      2019-11-18 17:00:00.0000000
1           2019-11-19 16:00:00.0000000      2019-11-19 17:00:00.0000000
2           2019-11-25 16:00:00.0000000      2019-11-25 17:00:00.0000000
1           2019-11-25 17:00:00.0000000      2019-11-25 18:00:00.0000000

預期輸出:

Name             StartDate             EndDate                ResourceKey
tk1-Room1        2019-11-25 17:00:00   2019-11-25 17:00:00    1
tk1-Room2        2019-11-25 16:00:00   2019-11-25 17:00:00    2
tk1-noentries    NULL                  NULL                   3

我試圖列出所有Calendar條目,以及它們相應的開始(最近)和結束時間。

我有以下部分工作的代碼:

SELECT Name,StartDate,ResourceKey FROM [Calendar].[dbo].[Calendar] CAL
LEFT JOIN(
    SELECT 
        CalendarId, 
        MAX(ENT.[Start]) as StartDate
    FROM [CalendarEntry] ENT
    GROUP BY CalendarId
    )
AS ST on CAL.CalendarId = ST.CalendarId

但是,如果我要包含該列,則在我的子 SELECT 中,EG:

    SELECT 
        CalendarId, 
        MAX(ENT.[Start]) as StartDate,
        ENT.[End] as endDate

我收到以下錯誤:

Column 'CalendarEntry.End' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

但是,現在將它包含在 GROUP BY 中會導致多個 CalendarEntry Rows 為每個日歷返回。

我從 CalendarEntry 中獲取最新行的最佳方式是什么,它允許我訪問所有列?

謝謝!

這是典型的每組前 1 個問題。

您可以使用row_number()

select *
from (
    select 
        c.*,
        e.*,
        row_number() over(partition by c.CalendarId order by e.Start desc) rn
    from [Calendar].[dbo].[Calendar] c
    left join [CalendarEntry] e ON c.CalendarId = e.CalendarId
) t
where rn = 1

或者您可以使用相關子查詢進行過濾:

select c.*, e.*
from [Calendar].[dbo].[Calendar] c
left join [CalendarEntry] e 
    on c.CalendarId = e.CalendarId
    and c.Start = (
        select max(e1.Start) from [CalendarEntry] e where c.CalendarId = e1.CalendarId
    ) 

我試圖列出所有日歷條目,以及它們相應的開始(最近)和結束時間。

我將此解釋為CalendarEntry中每個CalendarId最新記錄:

select ce.*
from CalendarEntry ce
where ce.StartDate = (select max(ce2.StartDate)
                      from CalendarEntry ce2
                      where ce2.CalendarId = ce.CalendarId
                     );

您也可以嘗試OUTER APPLY ,但是@GMB的答案是從性能角度來看更好的方法

SELECT Name,
       StartDate,
       EndDate,
       ResourceKey
FROM dbo.Calendar AS C
    OUTER APPLY
(
    SELECT TOP 1 *
    FROM dbo.CalendarEntry
    WHERE CalendarId = C.CalendarId
    ORDER BY StartDate DESC,
             EndDate DESC
) AS K;

您也可以嘗試LAST_VALUE / FIRST_VALUE (在 SQL Server 2012 及更高版本中可用)函數,如下所示,但是再次@GMB的答案是從性能角度來看更好的方法:

SELECT DISTINCT
       Name,
       LAST_VALUE(StartDate) OVER (PARTITION BY C.CalendarId
                                   ORDER BY StartDate,EndDate
                                   ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING),
       LAST_VALUE(EndDate) OVER (PARTITION BY C.CalendarId
                                 ORDER BY StartDate,EndDate
                                 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING),
       ResourceKey
FROM dbo.Calendar AS C
    LEFT JOIN dbo.CalendarEntry
        ON CalendarEntry.CalendarId = C.CalendarId;

如果要使用 FIRST_VALUE 函數,則應按如下方式重寫順序:

ORDER BY StartDate DESC,EndDate DESC

而且您也不需要指定ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING部分

SELECT DISTINCT
       Name,
       FIRST_VALUE(StartDate) OVER (PARTITION BY C.CalendarId
                                   ORDER BY StartDate DESC,EndDate DESC),
       FIRST_VALUE(EndDate) OVER (PARTITION BY C.CalendarId
                                 ORDER BY StartDate DESC,EndDate DESC),
       ResourceKey
FROM dbo.Calendar AS C
    LEFT JOIN dbo.CalendarEntry
        ON CalendarEntry.CalendarId = C.CalendarId;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM