[英]Order By One One Column in MSSQL
I Have the following SQL Tables:我有以下 SQL 表:
[Calendar] [日历]
[CalendarId]
[Name]
SAMPLE DATA:样本数据:
CalendarId ResourceKey Name
1 1 tk1-Room1
2 2 tk1-Room2
3 3 tk1-noentries
[CalendarEntry] [日历条目]
[CalendarId]
[CalendarEntryId]
[Start]
[End]
SAMPLE DATA:样本数据:
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
Expected output:预期输出:
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
I am trying to list all Calendar
entries, with their corresponding Start(Most Recent) and End Times.我试图列出所有
Calendar
条目,以及它们相应的开始(最近)和结束时间。
I have the following code which is working partially:我有以下部分工作的代码:
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
However, If i was to include that column, In my sub SELECT, EG:但是,如果我要包含该列,则在我的子 SELECT 中,EG:
SELECT
CalendarId,
MAX(ENT.[Start]) as StartDate,
ENT.[End] as endDate
I get the following error:我收到以下错误:
Column 'CalendarEntry.End' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
However, including it in the GROUP BY now causes Multiple CalendarEntry Rows to come back for each Calendar..但是,现在将它包含在 GROUP BY 中会导致多个 CalendarEntry Rows 为每个日历返回。
What is the best way for me to grab the most recent row out of CalendarEntry which allows me access to all the columns?我从 CalendarEntry 中获取最新行的最佳方式是什么,它允许我访问所有列?
Thanks!谢谢!
This is a typical top 1 per group question.这是典型的每组前 1 个问题。
You can either use row_number()
:您可以使用
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
Or you can filter with a correlated subquery:或者您可以使用相关子查询进行过滤:
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
)
I am trying to list all Calendar entries, with their corresponding Start(Most Recent) and End Times.
我试图列出所有日历条目,以及它们相应的开始(最近)和结束时间。
I interpret this as the most recent record from CalendarEntry
for each CalendarId
:我将此解释为
CalendarEntry
中每个CalendarId
最新记录:
select ce.*
from CalendarEntry ce
where ce.StartDate = (select max(ce2.StartDate)
from CalendarEntry ce2
where ce2.CalendarId = ce.CalendarId
);
You can try OUTER APPLY too, however @GMB 's answer is a better approach from performance prospective您也可以尝试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;
You can also try LAST_VALUE / FIRST_VALUE (available in SQL Server 2012 and later) functions too, as below, , however again @GMB 's answer is a better approach from performance prospective:您也可以尝试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;
If you want to use FIRST_VALUE function, then you should rewrite the order by as below:如果要使用 FIRST_VALUE 函数,则应按如下方式重写顺序:
ORDER BY StartDate DESC,EndDate DESC
And you also you will not need to specify the ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
section而且您也不需要指定
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.