[英]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.