在MSSQL中按一列排序
我有以下SQL表: [日历]在MSSQL中按一列排序,sql,sql-server,tsql,date,greatest-n-per-group,Sql,Sql Server,Tsql,Date,Greatest N Per Group,我有以下SQL表: [日历] [CalendarId] [Name] 样本数据: CalendarId ResourceKey Name 1 1 tk1-Room1 2 2 tk1-Room2 3 3 tk1-noentries CalendarId Start End 1
[CalendarId]
[Name]
样本数据:
CalendarId ResourceKey Name
1 1 tk1-Room1
2 2 tk1-Room2
3 3 tk1-noentries
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
[日历条目]
[CalendarId]
[CalendarEntryId]
[Start]
[End]
样本数据:
CalendarId ResourceKey Name
1 1 tk1-Room1
2 2 tk1-Room2
3 3 tk1-noentries
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
我试图列出所有日历
条目及其相应的开始(最近)和结束时间
我有以下部分工作的代码:
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
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.
但是,现在将其包含在组中会导致每个日历返回多个CalendarEntry行
对于我来说,从允许我访问所有列的CalendarEntry中获取最近一行的最佳方法是什么
谢谢 这是一个典型的每组前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
)
这是一个典型的每组前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
)
我试图列出所有日历条目,以及它们相应的开始(最近)和结束时间
我将此解释为每个CalendarId
的CalendarEntry
中的最新记录:
select ce.*
from CalendarEntry ce
where ce.StartDate = (select max(ce2.StartDate)
from CalendarEntry ce2
where ce2.CalendarId = ce.CalendarId
);
我试图列出所有日历条目,以及它们相应的开始(最近)和结束时间
我将此解释为每个CalendarId
的CalendarEntry
中的最新记录:
select ce.*
from CalendarEntry ce
where ce.StartDate = (select max(ce2.StartDate)
from CalendarEntry ce2
where ce2.CalendarId = ce.CalendarId
);
你也可以尝试,但是从性能角度来看,我们的答案是更好的方法
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;
您也可以尝试/(在SQL Server 2012及更高版本中提供)函数,如下所示,不过从性能角度来看,我们的答案还是更好的:
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
而且,您也不需要指定无界前向和无界后向之间的行
部分
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;
你也可以尝试,但是从性能角度来看,我们的答案是更好的方法
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;
您也可以尝试/(在SQL Server 2012及更高版本中提供)函数,如下所示,不过从性能角度来看,我们的答案还是更好的:
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
而且,您也不需要指定无界前向和无界后向之间的行
部分
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;
样本数据和预期结果将有所帮助。您的代码中有未作为表的一部分提及的列。当GROUP BY、UNION和SELECT DISTINCT时,ORDER BY中只能使用SELECT列表项。非常有意义。样本数据和期望的结果会有所帮助。您的代码中有未作为表的一部分提及的列。当GROUP BY、UNION和SELECT DISTINCT时,ORDER BY中只能使用SELECT列表项。这很有道理。但这不会被证明是日历。名称@VigneshKumarA。如果需要,您可以在外部查询中轻松地
加入它。在这种情况下,将丢失CalendarId=3的记录!但这不会被证明是日历。名称
@VigneshKumarA。如果需要,您可以在外部查询中轻松地加入它。在这种情况下,将丢失CalendarId=3的记录!这是有效的,但仔细检查,似乎任何没有任何条目的日历都不会被返回。。。我的测试数据包含13个日历,只有12个有条目。我只得到了12个结果。这是有效的,但仔细检查,似乎任何没有任何条目的日历都不会被返回。。。我的测试数据包含13个日历,只有12个有条目。我只得到了12个结果。