我正在尝试找到一种方法来增强我的SQL查询。有人可以推荐我最好的方法来优化这个查询。总之,我想让它更快。此查询用于计算目前位于看台内的人数,每直至此HOUR 。我必须获得每张票的最大LogDatetime ,直到那个小时,然后将其加入基本视图,这样我就可以获得日志信息(日志位置和日志类型)。 LogType = 1是Checkin票,0 = Checkout。
这是查询:
SELECT DISTINCT fld.Grandstand,log9h.LogHour,Count(log9h.TicketNo) AS TotalOccupancy
FROM (
SELECT DISTINCT TicketNo, logDay,9 as Loghour, MAX(LogDateTime) AS LastLog
FROM dbo.viewF1LogDetail
WHERE LogDay = 14 AND LogHour < = 9
GROUP BY TicketNo, logDay
) AS log9h
INNER JOIN dbo.viewF1LogDetail AS fld ON fld.TicketNo = log9h.TicketNo
AND fld.LogDateTime = log9h.LastLog
WHERE (fld.ScanningLogLocationType =('Grandstand')) AND (fld.LogType = 1)
GROUP BY fld.Grandstand,log9h.LogHour
UNION
SELECT DISTINCT fld.Grandstand,log10h.LogHour,Count(log10h.TicketNo) AS TotalOccupancy
FROM (
SELECT DISTINCT TicketNo, logDay,10 as Loghour, MAX(LogDateTime) AS LastLog
FROM dbo.viewF1LogDetail
WHERE LogDay = 14 AND LogHour < = 10
GROUP BY TicketNo, logDay
) AS log10h
INNER JOIN dbo.viewF1LogDetail AS fld ON fld.TicketNo = log10h.TicketNo
AND fld.LogDateTime = log10h.LastLog
WHERE (fld.ScanningLogLocationType =('Grandstand')) AND (fld.LogType = 1)
GROUP BY fld.Grandstand,log10h.LogHour
UNION
SELECT DISTINCT fld.Grandstand,log11h.LogHour,Count(log11h.TicketNo) AS TotalOccupancy
FROM (
SELECT DISTINCT TicketNo, logDay,11 as Loghour, MAX(LogDateTime) AS LastLog
FROM dbo.viewF1LogDetail
WHERE LogDay = 14 AND LogHour < = 11
GROUP BY TicketNo, logDay
) AS log11h
INNER JOIN dbo.viewF1LogDetail AS fld ON fld.TicketNo = log11h.TicketNo
AND fld.LogDateTime = log11h.LastLog
WHERE (fld.ScanningLogLocationType =('Grandstand')) AND (fld.LogType = 1)
GROUP BY fld.Grandstand,log11h.LogHour
UNION
SELECT DISTINCT fld.Grandstand,log12h.LogHour,Count(log12h.TicketNo) AS TotalOccupancy
FROM (
SELECT DISTINCT TicketNo, logDay,12 as Loghour, MAX(LogDateTime) AS LastLog
FROM dbo.viewF1LogDetail
WHERE LogDay = 14 AND LogHour < = 12
GROUP BY TicketNo, logDay
) AS log12h
INNER JOIN dbo.viewF1LogDetail AS fld ON fld.TicketNo = log12h.TicketNo
AND fld.LogDateTime = log12h.LastLog
WHERE (fld.ScanningLogLocationType =('Grandstand')) AND (fld.LogType = 1)
GROUP BY fld.Grandstand,log12h.LogHour
UNION
SELECT DISTINCT fld.Grandstand,log13h.LogHour,Count(log13h.TicketNo) AS TotalOccupancy
FROM (
SELECT DISTINCT TicketNo, logDay,13 as Loghour, MAX(LogDateTime) AS LastLog
FROM dbo.viewF1LogDetail
WHERE LogDay = 14 AND LogHour < = 13
GROUP BY TicketNo, logDay
) AS log13h
INNER JOIN dbo.viewF1LogDetail AS fld ON fld.TicketNo = log13h.TicketNo
AND fld.LogDateTime = log13h.LastLog
WHERE (fld.ScanningLogLocationType =('Grandstand')) AND (fld.LogType = 1)
GROUP BY fld.Grandstand,log13h.LogHour
UNION
SELECT DISTINCT fld.Grandstand,log14h.LogHour,Count(log14h.TicketNo) AS TotalOccupancy
FROM (
SELECT DISTINCT TicketNo, logDay,14 as Loghour, MAX(LogDateTime) AS LastLog
FROM dbo.viewF1LogDetail
WHERE LogDay = 14 AND LogHour < = 14
GROUP BY TicketNo, logDay
) AS log14h
INNER JOIN dbo.viewF1LogDetail AS fld ON fld.TicketNo = log14h.TicketNo
AND fld.LogDateTime = log14h.LastLog
WHERE (fld.ScanningLogLocationType =('Grandstand')) AND (fld.LogType = 1)
GROUP BY fld.Grandstand,log14h.LogHour
UNION
SELECT DISTINCT fld.Grandstand,log15h.LogHour,Count(log15h.TicketNo) AS TotalOccupancy
FROM (
SELECT DISTINCT TicketNo, logDay,15 as Loghour, MAX(LogDateTime) AS LastLog
FROM dbo.viewF1LogDetail
WHERE LogDay = 14 AND LogHour < = 15
GROUP BY TicketNo, logDay
) AS log15h
INNER JOIN dbo.viewF1LogDetail AS fld ON fld.TicketNo = log15h.TicketNo
AND fld.LogDateTime = log15h.LastLog
WHERE (fld.ScanningLogLocationType =('Grandstand')) AND (fld.LogType = 1)
GROUP BY fld.Grandstand,log15h.LogHour
ORDER BY Grandstand,Loghour
示例数据:
Grandstand LogHour TotalOccupancy
Main 11 11
Main 12 15
Main 13 12
Main 14 14
Main 15 22
Main 16 25
Main 17 31
Main 18 22
Main 19 11
West 10 2
West 11 22
West 12 23
West 13 24
West 14 55
West 15 56
West 16 57
West 17 22
West 18 23
West 19 11
South 10 22
South 11 21
South 12 26
South 13 55
South 14 56
South 15 78
South 16 99
South 17 22
South 18 11
South 19 1
不是一个令人信服的查询吗?提前感谢您的推荐。
答案 0 :(得分:1)
如果没有看到一些示例行和预期结果,那么理解这个问题就有点困难了。这会有用吗?
SELECT Grandstand,
LogHour,
COUNT(TicketNo) AS TotalOccupancy
FROM dbo.viewF1LogDetail
WHERE LogDay = 14
AND ScanningLogLocationType = 'Grandstand'
AND LogType = 1
AND LogHour >= 9
AND LogHour <= 15
GROUP BY Grandstand,
LogHour;
如果这不起作用,对原因的解释可能会揭示查询的真实意图。
更新:
我想我现在明白了一点。试试这个:
WITH hourRows AS
( /* Get a base set of hours in the day */
SELECT TOP (24)
ROW_NUMBER() OVER (ORDER BY name) hr
FROM sys.objects
), ticketInfo AS (
/* Return the check in log event */
SELECT ld1.Grandstand,
ld1.LogHour AS CheckInHour,
checkout.LogHour AS CheckOutHour,
ld1.TicketNo
FROM viewF1LogDetail ld1
CROSS APPLY ( /* Apply the check out time to the set */
SELECT ld2.LogHour
FROM viewF1LogDetail ld2
WHERE ld2.LogDay = 14
AND ld2.ScanningLogLocationType = 'Grandstand'
AND ld2.LogType = 0
AND ld2.LogHour >= 9
AND ld2.LogHour <= 15
AND ld1.Grandstand = ld2.Grandstand
AND ld1.TicketNo = ld2.TicketNo
) checkout
WHERE ld1.LogDay = 14
AND ld1.ScanningLogLocationType = 'Grandstand'
AND ld1.LogType = 1
AND ld1.LogHour >= 9
AND ld1.LogHour <= 15
)
SELECT ci.GrandStand,
hr.hr AS LogHour,
COUNT(ci.TicketNo) AS TotalOccupancy
FROM hourRows hr
INNER JOIN ticketInfo ci ON hr.hr >= ci.CheckInHour
AND hr.hr <= ci.CheckOutHour
GROUP BY ci.GrandStand,
hr.hr
ORDER BY ci.Grandstand;
请注意,您应该使用实数Numbers表替换hourRows CTE中的sys.objects。