Sql 基于并集的多查询优化
我正试图找到一种方法来增强我的SQL查询。有人能推荐我优化这个查询的最佳方法吗。简言之,我想让它更快。此查询用于计算截至本小时每个正面看台内的当前人数。我必须获取每个票证的max LogDatetime,直到该小时,然后将其加入基本视图,以便获取日志信息(日志位置和日志类型)。 LogType=1表示签入票据,0表示签出 以下是查询:Sql 基于并集的多查询优化,sql,sql-server,Sql,Sql Server,我正试图找到一种方法来增强我的SQL查询。有人能推荐我优化这个查询的最佳方法吗。简言之,我想让它更快。此查询用于计算截至本小时每个正面看台内的当前人数。我必须获取每个票证的max LogDatetime,直到该小时,然后将其加入基本视图,以便获取日志信息(日志位置和日志类型)。 LogType=1表示签入票据,0表示签出 以下是查询: SELECT DISTINCT fld.Grandstand,log9h.LogHour,Count(log9h.TicketNo) AS TotalOccupa
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
这不是一个令人信服的问题,对吗?提前感谢您的建议。如果看不到一些示例行和预期结果,理解这个问题有点困难。这样行吗
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;
选择正面看台,
对数小时,
将(票号)计入总占用率
从dbo.viewF1LogDetail
其中LogDay=14
和ScanningLogLocationType=‘正面看台’
和LogType=1
和对数小时>=9
所以没什么错,除了你想让它更快?你应该试着在这里发帖:谢谢@Steve。。会的。顺便说一句,你想让更多的人来做这件事,让他们更容易帮助你。添加一个脚本来生成表和一些示例数据。我通常会跳过这些问题,因为问问题的人表明他们很想得到帮助,而不仅仅是让其他人为他们做这些工作。据我所知,这会每小时发生变化,而不是累计到每小时。嗨,我现在添加了一些示例行。此查询对我不起作用,因为它将只计算票证的所有签入。我需要的是在给定的日志小时之前获取票据的状态。比如说001号车票在主看台一直到第14小时,但在第15小时离开。因此,在第14小时,他将被包括在总入住人数中,但在第15小时之前,他不会被包括在总入住人数中,因为他已经离开主看台。看看我添加的新查询是否更好。您好@JonBoulineau,您的查询有一个很好的概念,但运行时间比我之前的查询要长。不过,这是一个非常有条理的查询。谢谢你提出新的想法。
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;