我有以下SQL脚本,它当前显示基于给定时间的时间范围内的行数。例如。在给定时间之前15分钟和之后15分钟,在时间之前30分钟和之后30分钟等。它可以正常工作,但出于性能考虑,我需要从联合中更改它。关于如何通过单个select / table实现此目标的其他方法有什么想法吗?
DECLARE @GameNumber int
DECLARE @EventType int
SET @GameNumber = 116
SET @EventType = 1
SELECT 'Between -120 mins and -90 mins' as TimePeriod
,COUNT(*)
FROM attendance ta
LEFT OUTER JOIN SubStations sub
ON TA_ServiceNumber = sub.ServiceNumber
AND TA_DoorNumber = sub.DoorNumber
INNER JOIN [dbo].[Products] pro
ON ta.TA_GameNumber = pro.prd_GameNumber
INNER JOIN dbo.producttypes prot
ON ta.Eventtype = prot.PRD_TypeID AND @EventType = prot.PRD_EventTypeID
WHERE GameNumber = @GameNumber
AND EventType = @EventType
AND ta.TA_TimeAndDate BETWEEN DATEADD(minute, -120, pro.GameTime) AND DATEADD(minute, -90, pro.GameTime)
UNION ALL
SELECT 'Between -90 mins and -60 mins' as TimePeriod
,COUNT(*) AS Flow
FROM attendance ta
INNER JOIN TA_OperationCode toc
ON ta.TA_OperationCode = toc.OperationCode
LEFT OUTER JOIN SubStations sub
ON TA_ServiceNumber = sub.ServiceNumber
AND TA_DoorNumber = sub.DoorNumber
INNER JOIN [dbo].[Products] pro
ON ta.TA_GameNumber = pro.prd_GameNumber
INNER JOIN dbo.producttypes prot
ON ta.TA_Eventtype = prot.PRD_TypeID AND @EventType = prot.PRD_EventTypeID
WHERE GameNumber = @GameNumber
AND EventType = @EventType
AND ta.TA_TimeAndDate BETWEEN DATEADD(minute, -90, pro.GameTime) AND DATEADD(minute, -60, pro.GameTime)
UNION ALL
SELECT 'Between -60 mins and -45 mins' as TimePeriod
,COUNT(*) AS Flow
FROM attendance ta
INNER JOIN TA_OperationCode toc
ON ta.TA_OperationCode = toc.OperationCode
LEFT JOIN SubStationssub
ON TA_ServiceNumber = sub.ServiceNumber
AND TA_DoorNumber = sub.DoorNumber
INNER JOIN [dbo].[Products] pro
ON ta.TA_GameNumber = pro.prd_GameNumber
INNER JOIN dbo.producttypes prot
ON ta.TA_Eventtype = prot.PRD_TypeID AND @EventType = prot.PRD_EventTypeID
WHERE GameNumber = @GameNumber
AND EventType = @EventType
AND ta.TA_TimeAndDate BETWEEN DATEADD(minute, -60, pro.GameTime) AND DATEADD(minute, -45, pro.GameTime)
答案 0 :(得分:2)
将GROUP BY
与CASE
表达式一起使用:
SELECT v.TimePeriod, COUNT(*)
FROM attendance ta LEFT OUTER JOIN
SubStations sub
ON TA_ServiceNumber = sub.ServiceNumber AND
TA_DoorNumber = sub.DoorNumber INNER JOIN
[dbo].[Products] pro
ON ta.TA_GameNumber = pro.prd_GameNumber INNER JOIN
dbo.producttypes prot
ON ta.Eventtype = prot.PRD_TypeID AND
@EventType = prot.PRD_EventTypeID CROSS APPLY
(VALUES (CASE WHEN ta.TA_TimeAndDate BETWEEN DATEADD(minute, -120, pro.GameTime) AND DATEADD(minute, -90, pro.GameTime)
THEN 'Between -90 mins and -60 mins'
WHEN ta.TA_TimeAndDate BETWEEN DATEADD(minute, -90, pro.GameTime) AND DATEADD(minute, -60, pro.GameTime)
THEN 'Between -90 mins and -60 mins'
. . .
END)
) v(TimePeriod)
WHERE GameNumber = @GameNumber AND EventType = @EventType
GROUP BY v.TimePeriod
ORDER BY MIN(ta.TA_TimeAndDate);
答案 1 :(得分:1)
为什么不简单地按案例陈述使用GROUP BY: EG
select
case
when ta.TA_TimeAndDate BETWEEN DATEADD(minute, -120, pro.GameTime) AND DATEADD(minute, -90, pro.GameTime)
then 'Between -120 mins and -90 mins'
when ta.TA_TimeAndDate BETWEEN DATEADD(minute, -90, pro.GameTime) AND DATEADD(minute, -60, pro.GameTime)
then 'Between -90 mins and -60 mins'
when ta.TA_TimeAndDate BETWEEN DATEADD(minute, -60, pro.GameTime) AND DATEADD(minute, -45, pro.GameTime)
then 'Between -60 mins and -45 mins'
else ''
END
as TimePeriod,
count(*) as Flow
FROM attendance ta
INNER JOIN TA_OperationCode toc
ON ta.TA_OperationCode = toc.OperationCode
LEFT OUTER JOIN SubStations sub
ON TA_ServiceNumber = sub.ServiceNumber
AND TA_DoorNumber = sub.DoorNumber
INNER JOIN [dbo].[Products] pro
ON ta.TA_GameNumber = pro.prd_GameNumber
INNER JOIN dbo.producttypes prot
ON ta.TA_Eventtype = prot.PRD_TypeID AND @EventType = prot.PRD_EventTypeID
WHERE GameNumber = @GameNumber
AND EventType = @EventType
AND ta.TA_TimeAndDate BETWEEN DATEADD(minute, -120, pro.GameTime) AND DATEADD(minute, -45, pro.GameTime)
group by
case
when ta.TA_TimeAndDate BETWEEN DATEADD(minute, -120, pro.GameTime) AND DATEADD(minute, -90, pro.GameTime)
then 'Between -120 mins and -90 mins'
when ta.TA_TimeAndDate BETWEEN DATEADD(minute, -90, pro.GameTime) AND DATEADD(minute, -60, pro.GameTime)
then 'Between -90 mins and -60 mins'
when ta.TA_TimeAndDate BETWEEN DATEADD(minute, -60, pro.GameTime) AND DATEADD(minute, -45, pro.GameTime)
then 'Between -60 mins and -45 mins'
else ''
END
如果内部连接差异很重要,则可以将其添加为左连接,并在`clause eg:
中检查是否为null。AND (toc.OperationCode is not null or ta.TA_TimeAndDate > DATEADD(minute, -90, pro.GameTime))
`