SQL 2008 中临时表或子查询的多重联接

发布于 2024-09-14 21:18:44 字数 1037 浏览 8 评论 0原文

我有以下 SQL,它获取一系列日期中每天的季节,然后按开始日期和结束日期以及夜晚数对每个季节进行分组。它的作用并不重要,但我的问题是哪个更好,我在下面完成的方式或每次在第二个查询中使用 @dateSeasons 时使用第一个 select 语句作为子查询。两种方式似乎运行相同,但这种方式看起来更整洁。

DECLARE @dateSeasons TABLE ([date] date, seasonID int)

INSERT INTO @dateSeasons
SELECT D.[date], S.ID
FROM @dates AS D
CROSS APPLY (

    SELECT TOP 1 ID
    FROM dbo.Seasons
    WHERE bookingID = @bookingID 
    AND D.[date] BETWEEN startDate AND endDate
    ORDER BY ID DESC

) AS S


SELECT MIN([date]), endDate, DATEDIFF(DAY, MIN([date]), DATEADD(DAY, 1, endDate)), seasonID
FROM (

    SELECT S1.seasonID, S1.[date], (

        SELECT MAX([date])
        FROM @dateSeasons S2
        WHERE S2.seasonID = S1.seasonID
        AND NOT EXISTS (

            SELECT NULL
            FROM @dateSeasons S3
            WHERE S3.[date] < S2.[date]
            AND S3.[date] > S1.[date]
            AND S3.seasonID <> S1.seasonID

        )

    ) AS endDate
    FROM @dateSeasons S1
) AS results
GROUP BY endDate, seasonID
ORDER BY MIN([date])

I have the following SQL which gets a season for each day in a range of dates, then groups each season by start and end date with number of nights. What it does is not important but my question is which is better, the way I've done it below or use the first select statement as a subquery each time @dateSeasons is used in the second query. Both ways seem to run the same but this way looks neater.

DECLARE @dateSeasons TABLE ([date] date, seasonID int)

INSERT INTO @dateSeasons
SELECT D.[date], S.ID
FROM @dates AS D
CROSS APPLY (

    SELECT TOP 1 ID
    FROM dbo.Seasons
    WHERE bookingID = @bookingID 
    AND D.[date] BETWEEN startDate AND endDate
    ORDER BY ID DESC

) AS S


SELECT MIN([date]), endDate, DATEDIFF(DAY, MIN([date]), DATEADD(DAY, 1, endDate)), seasonID
FROM (

    SELECT S1.seasonID, S1.[date], (

        SELECT MAX([date])
        FROM @dateSeasons S2
        WHERE S2.seasonID = S1.seasonID
        AND NOT EXISTS (

            SELECT NULL
            FROM @dateSeasons S3
            WHERE S3.[date] < S2.[date]
            AND S3.[date] > S1.[date]
            AND S3.seasonID <> S1.seasonID

        )

    ) AS endDate
    FROM @dateSeasons S1
) AS results
GROUP BY endDate, seasonID
ORDER BY MIN([date])

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光磨忆 2024-09-21 21:18:44

看起来整洁与编写 SQL 代码无关。从性能的角度来看,看起来优雅的方法通常是解决问题的最差方式。

确定哪种方法最好的唯一方法是首先确保您测试的两种方法返回相同的结果,然后对它们进行性能测试并检查执行计划(或在 mySQL 中解释)。使查询更好的技术也是特定于数据库的。在 SQL Server 中最适合性能调整的方法可能在 Oracle 中最不可行。

Looking neater is irrelevant in writing SQL Code. What looks elegant is often the worst possible way to solve the problem from a performance standpoint.

The only way to know for sure which is best is to first make sure both ways you are testing return the same results and then performance test them and check out the execution plans (or explain in mySQL). Techniques which make the query better are database specific as well. What works best to performance tune in SQL Server might be the worst possibility in Oracle.

疯了 2024-09-21 21:18:44

有时,使用公用表表达式 (CTE) 可以获得更好的性能:

WITH
dateSeasons ([date], [seasonID])
AS
(
    SELECT D.[date], S.ID
    FROM @dates AS D
    CROSS APPLY (

        SELECT TOP 1 ID
        FROM dbo.Seasons
        WHERE bookingID = @bookingID 
        AND D.[date] BETWEEN startDate AND endDate
        ORDER BY ID DESC

    ) AS S
)

SELECT MIN([date]), endDate, DATEDIFF(DAY, MIN([date]), DATEADD(DAY, 1, endDate)), seasonID
FROM (

    SELECT S1.seasonID, S1.[date], (

        SELECT MAX([date])
        FROM dateSeasons S2
        WHERE S2.seasonID = S1.seasonID
        AND NOT EXISTS (

            SELECT NULL
            FROM dateSeasons S3
            WHERE S3.[date] < S2.[date]
            AND S3.[date] > S1.[date]
            AND S3.seasonID <> S1.seasonID

        )

    ) AS endDate
    FROM dateSeasons S1
) AS results
GROUP BY endDate, seasonID
ORDER BY MIN([date])

Sometimes you can get better performance by using a common table expression (CTE):

WITH
dateSeasons ([date], [seasonID])
AS
(
    SELECT D.[date], S.ID
    FROM @dates AS D
    CROSS APPLY (

        SELECT TOP 1 ID
        FROM dbo.Seasons
        WHERE bookingID = @bookingID 
        AND D.[date] BETWEEN startDate AND endDate
        ORDER BY ID DESC

    ) AS S
)

SELECT MIN([date]), endDate, DATEDIFF(DAY, MIN([date]), DATEADD(DAY, 1, endDate)), seasonID
FROM (

    SELECT S1.seasonID, S1.[date], (

        SELECT MAX([date])
        FROM dateSeasons S2
        WHERE S2.seasonID = S1.seasonID
        AND NOT EXISTS (

            SELECT NULL
            FROM dateSeasons S3
            WHERE S3.[date] < S2.[date]
            AND S3.[date] > S1.[date]
            AND S3.seasonID <> S1.seasonID

        )

    ) AS endDate
    FROM dateSeasons S1
) AS results
GROUP BY endDate, seasonID
ORDER BY MIN([date])
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文