Sql 基于并集的多查询优化

Sql 基于并集的多查询优化,sql,sql-server,Sql,Sql Server,我正试图找到一种方法来增强我的SQL查询。有人能推荐我优化这个查询的最佳方法吗。简言之,我想让它更快。此查询用于计算截至本小时每个正面看台内的当前人数。我必须获取每个票证的max LogDatetime,直到该小时,然后将其加入基本视图,以便获取日志信息(日志位置和日志类型)。 LogType=1表示签入票据,0表示签出 以下是查询: SELECT DISTINCT fld.Grandstand,log9h.LogHour,Count(log9h.TicketNo) AS TotalOccupa

我正试图找到一种方法来增强我的SQL查询。有人能推荐我优化这个查询的最佳方法吗。简言之,我想让它更快。此查询用于计算截至本小时每个正面看台内的当前人数。我必须获取每个票证的max LogDatetime,直到该小时,然后将其加入基本视图,以便获取日志信息(日志位置和日志类型)。 LogType=1表示签入票据,0表示签出

以下是查询:

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;