【问题标题】:How can this T-SQL query be optimized?如何优化这个 T-SQL 查询?
【发布时间】:2013-05-27 10:23:19
【问题描述】:

我对 sql 比较陌生,我希望得到一些帮助。基本上,我试图在查询中进行一些计算,因为函数有点慢。你们能改进一下吗?

-- Query to retrive ADA from every school
Select  Distinct DY, 
        DATENAME(MM,DT) as 'Month',
        CONVERT(nvarchar,DT,101) as 'Date',
        (
            Select ((@M_stu - (Select Count(SC) from dbo.ATT where sc=1 AND al!='' AND DY=T.DY))/@M_stu)*100
        ) as 'Merced ADA',
        (
            Select ((@A_stu - (Select Count(SC) from dbo.ATT where sc=2 AND al!='' AND DY=T.DY))/@A_stu)*100
        ) as 'Atwater ADA',
        (
            Select ((@L_stu - (Select Count(SC) from dbo.ATT where sc=3 AND al!='' AND DY=T.DY))/@L_stu)*100
        ) as 'Livingston ADA',
        (
            Select ((@B_stu - (Select Count(SC) from dbo.ATT where sc=4 AND al!='' AND DY=T.DY))/@B_stu)*100
        ) as 'Buhach ADA',
        (
            Select ((@Y_stu - (Select Count(SC) from dbo.ATT where sc=5 AND al!='' AND DY=T.DY))/@Y_stu)*100
        ) as 'Yosemite ADA',
        (
            Select ((@I_stu - (Select Count(SC) from dbo.ATT where sc=6 AND al!='' AND DY=T.DY))/@I_stu)*100
        ) as 'Independence ADA',
        (
            Select ((@G_stu - (Select Count(SC) from dbo.ATT where sc=10 AND al!='' AND DY=T.DY))/@G_stu)*100
        ) as 'Golden Valley ADA',
        (
            Select ((@S_stu - (Select Count(SC) from dbo.ATT where sc=92 AND al!='' AND DY=T.DY))/@S_stu)*100
        ) as 'Sequoia ADA'
From dbo.ATT as T
Order by DY ASC

【问题讨论】:

    标签: sql sql-server tsql


    【解决方案1】:

    试试这个

    Select  DY, 
            DATENAME(MM,DT) as 'Month',
            CONVERT(nvarchar,DT,101) as 'Date',
            @M_stu - (Count(case when sc=1 AND al!='' AND DY=T.DY then 1 else null end)/@M_stu)*100 as 'Merced ADA',
            @A_stu - (Count(case when sc=2 AND al!='' AND DY=T.DY then 1 else null end)/@A_stu)*100 as 'Atwater ADA',
            ...
    From dbo.ATT as T
    GROUP BY DY, DT
    Order by DY ASC
    

    【讨论】:

    • 删除 Distinct 并添加 Group By DY,你(几乎)就会拥有它。
    • 这很好用。它肯定会改善我的查询。我决定将代码放在视图中以调用查询,就好像它是一个普通的表一样,但现在我不能在查询中保留常量(@M_stu ect)。你知道解决这个问题的方法吗?
    • @me1223 不,您不能在视图中使用参数,但可以使用表函数。 stackoverflow.com/questions/1687279/…
    • 是的,我读过它们,但它们很慢,对吧?不管怎样,谢谢你这么快回复。
    【解决方案2】:

    试试这个解决方案:

    SELECT  DISTINCT 
            t.DY                            AS DY, 
            DATENAME(MM,t.DT)               AS [Month],
            CONVERT(NVARCHAR,t.DT,101)      AS [Date],
            ((@M_stu - d.[1])/@M_stu)*100   AS [Merced ADA],
            ((@A_stu - d.[2])/@A_stu)*100   AS [Atwater ADA],
            ((@L_stu - d.[3])/@L_stu)*100   AS [Livingston ADA],
            ((@B_stu - d.[4])/@B_stu)*100   AS [Buhach ADA],
            ((@Y_stu - d.[5])/@Y_stu)*100   AS [Yosemite ADA],
            ((@I_stu - d.[6])/@I_stu)*100   AS [Independence ADA],
            ((@G_stu - d.[10])/@G_stu)*100  AS [Golden Valley ADA],
            ((@S_stu - d.[92])/@S_stu)*100  AS [Sequoia ADA]
    FROM    dbo.ATT AS t
    OUTER APPLY (
        SELECT  c.*
        FROM (
            SELECT  a.sc
            FROM    dbo.ATT AS a
            WHERE   a.sc IN (1,2,3,4,5,6,10,92) 
            AND     a.al!='' 
            AND     a.DY=t.DY
        ) b
        PIVOT( COUNT(b.sc) FOR a.sc IN ([1],[2],[3],[4],[5],[6],[10],[92]) ) c
    ) d
    ORDER BY t.DY ASC;
    

    您还应该检查您是否具有以下索引之一:CREATE [UNIQUE] INDEX index_name ON dbo.ATT (DY, sc, al)CREATE [UNIQUE] INDEX index_name ON dbo.ATT (DY, sc) INCLUDE (al)

    【讨论】:

    • 遗憾的是,现在这对我来说有点太复杂了。你能告诉我你为什么决定使用 OUTER APPLY 吗?
    • 您想知道我为什么使用OUTER APPLY 而不是CROSS APPLY 还是想知道OUTER APPLY 是否比这8 个子查询更好? 1) 使用CROSS APPLY,如果DY 列允许并包含NULLs,您可能会丢失行。 2) OUTER APPLY 解决方案很紧凑,根据我的经验,PIVOT 执行计划往往表现良好。当然,你应该自己测试和决定。当您有与性能相关的问题时,您应该发布所有索引以获得正确的答案。
    • 好的,谢谢。我在编写 sql 查询方面还是有点新意,所以我尽量保持对我的可读性。很可能一旦我获得经验,我将能够正确使用 OUTER APPLY。再次感谢您
    【解决方案3】:

    您必须将结果与当前查询进行比较,但我可能会这样做:

    Select  Distinct DY, 
            DATENAME(MM,DT) as Month,
            CONVERT(char(10),DT,101) as Date,
            @M_stu - sum(case when sc=1 then 1.0 else 0.0 end)/@M_stu)*100 as [Merced ADA],
            @A_stu - sum(case when sc=2 then 1.0 else 0.0 end)/@A_stu)*100 as [Atwater ADA],
            @L_stu - sum(case when sc=3 then 1.0 else 0.0 end)/@L_stu)*100 as [Livingston ADA],
            @B_stu - sum(case when sc=4 then 1.0 else 0.0 end)/@B_stu)*100 as [Buhach ADA],
            @Y_stu - sum(case when sc=5 then 1.0 else 0.0 end)/@Y_stu)*100 as [Yosemite ADA],
            @I_stu - sum(case when sc=6 then 1.0 else 0.0 end)/@I_stu)*100 as [Independence ADA],
            @G_stu - sum(case when sc=10 then 1.0 else 0.0 end)/@G_stu)*100 as [Golden Valley ADA],
            @S_stu - sum(case when sc=92 then 1.0 else 0.0 end)/@S_stu)*100 as [Sequoia ADA]
    From    dbo.ATT as T
    Where   al!=''
    Order by DY ASC
    

    如果没有要测试的样本数据,我认为这将是最简单的方法。

    【讨论】:

    • 你会如何把它放在一个视图中?
    • 把 create view 放在 select 语句之前,然后删除他的 order by
    猜你喜欢
    • 1970-01-01
    • 2022-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-01-05
    • 2014-11-04
    相关资源
    最近更新 更多