SQL联合的替代方法

时间:2019-05-02 10:34:03

标签: sql sql-server database

我有以下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)

2 个答案:

答案 0 :(得分:2)

GROUP BYCASE表达式一起使用:

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))

`

相关问题