UDF与子查询性能问题

时间:2013-06-10 11:07:17

标签: sql sql-server user-defined-functions

我已经尝试找出每个客户12个月的每月总销售额,总寄回值。

使用其他2个子查询,然后查询变为每行使用26个子查询,而sql语句非常大。

然后我创建了两个subselect for sale和sendback totals ...

结果查询变短但执行时间大于20-30次。

  1. 这是正常的
  2. 如果subqery返回NULL,我怎么能返回0 ..
  3. 编辑:

    (Select sum(chh2.cha_meblag)
     from dbo.CARI_HESAP_HAREKETLERI chh2
     where chh2.cha_normal_Iade=1 and
           chh2.cha_kod=ch.cari_kod and
           (chh2.cha_tarihi>='20130101' and chh2.cha_tarihi<='20130131')
    ) as Ocai
    

2 个答案:

答案 0 :(得分:1)

第二个问题的答案是将子查询包装在coalesce()

coalesce((Select sum(chh2.cha_meblag)
          from dbo.CARI_HESAP_HAREKETLERI chh2
          where chh2.cha_normal_Iade=1 and
                chh2.cha_kod=ch.cari_kod and
                (chh2.cha_tarihi>='20130101' and chh2.cha_tarihi<='20130131')
         ), '') as Ocai

正如Martin在评论中指出的那样,coalesce()具有我认为是SQL Server中的错误。在这种情况下,它将执行两次第一个表达式,一次检查NULL的值,第二次执行值。鉴于此,ISNULL()更好(即使我更喜欢标准函数):

isnull((Select sum(chh2.cha_meblag)
          from dbo.CARI_HESAP_HAREKETLERI chh2
          where chh2.cha_normal_Iade=1 and
                chh2.cha_kod=ch.cari_kod and
                (chh2.cha_tarihi>='20130101' and chh2.cha_tarihi<='20130131')
         ), '') as Ocai

答案 1 :(得分:1)

根据您的子查询,您可以在没有相关子查询的情况下解决您的问题,并且只使用联接。但是,只有一部分查询可以使用它很难确定。这就是为什么在发布问题时,尽可能多地发布相关代码是个好主意。尽管如此,从我收集的内容来看,你有这样的事情:

SELECT  (   SELECT  SUM(chh2.cha_meblag)
            FROM    dbo.CARI_HESAP_HAREKETLERI chh2
            WHERE   chh2.cha_normal_Iade = 1 
            AND     chh2.cha_kod = ch.cari_kod
            AND     chh2.cha_tarihi >= '20130101' 
            AND     chh2.cha_tarihi <= '20130131'
        ) AS Ocai,
        (   SELECT  SUM(chh2.cha_meblag)
            FROM    dbo.CARI_HESAP_HAREKETLERI chh2
            WHERE   chh2.cha_normal_Iade = 1 
            AND     chh2.cha_kod = ch.cari_kod
            AND     chh2.cha_tarihi >= '20130201' 
            AND     chh2.cha_tarihi <= '20130228'
        ) AS Ocai,
        ... etc for 12 months
FROM    SomeTable ch

你可以把它变成:

SELECT  ch.cari_kod,
        [20130101] = ISNULL([20130101], 0),
        [20130201] = ISNULL([20130201], 0),
        [20130301] = ISNULL([20130301], 0),
        [20130401] = ISNULL([20130401], 0),
        [20130501] = ISNULL([20130501], 0),
        [20130601] = ISNULL([20130601], 0),
        [20130701] = ISNULL([20130701], 0),
        [20130801] = ISNULL([20130801], 0),
        [20130901] = ISNULL([20130901], 0),
        [20131001] = ISNULL([20131001], 0),
        [20131101] = ISNULL([20131101], 0),
        [20131201] = ISNULL([20131201], 0)
FROM    SomeTable
        LEFT JOIN
        (   SELECT  chh2.cha_kod,
                    [20130101] = SUM(CASE WHEN chh2.cha_tarihi >= '20130101' AND chh2.cha_tarihi < '20130201' THEN chh2.cha_meblag ELSE 0 END),
                    [20130201] = SUM(CASE WHEN chh2.cha_tarihi >= '20130201' AND chh2.cha_tarihi < '20130301' THEN chh2.cha_meblag ELSE 0 END),
                    [20130301] = SUM(CASE WHEN chh2.cha_tarihi >= '20130301' AND chh2.cha_tarihi < '20130401' THEN chh2.cha_meblag ELSE 0 END),
                    [20130401] = SUM(CASE WHEN chh2.cha_tarihi >= '20130401' AND chh2.cha_tarihi < '20130501' THEN chh2.cha_meblag ELSE 0 END),
                    [20130501] = SUM(CASE WHEN chh2.cha_tarihi >= '20130501' AND chh2.cha_tarihi < '20130601' THEN chh2.cha_meblag ELSE 0 END),
                    [20130601] = SUM(CASE WHEN chh2.cha_tarihi >= '20130601' AND chh2.cha_tarihi < '20130701' THEN chh2.cha_meblag ELSE 0 END),
                    [20130701] = SUM(CASE WHEN chh2.cha_tarihi >= '20130701' AND chh2.cha_tarihi < '20130801' THEN chh2.cha_meblag ELSE 0 END),
                    [20130801] = SUM(CASE WHEN chh2.cha_tarihi >= '20130801' AND chh2.cha_tarihi < '20130901' THEN chh2.cha_meblag ELSE 0 END),
                    [20130901] = SUM(CASE WHEN chh2.cha_tarihi >= '20130901' AND chh2.cha_tarihi < '20131001' THEN chh2.cha_meblag ELSE 0 END),
                    [20131001] = SUM(CASE WHEN chh2.cha_tarihi >= '20131001' AND chh2.cha_tarihi < '20131101' THEN chh2.cha_meblag ELSE 0 END),
                    [20131101] = SUM(CASE WHEN chh2.cha_tarihi >= '20131101' AND chh2.cha_tarihi < '20131201' THEN chh2.cha_meblag ELSE 0 END),
                    [20131201] = SUM(CASE WHEN chh2.cha_tarihi >= '20131201' AND chh2.cha_tarihi < '20140101' THEN chh2.cha_meblag ELSE 0 END)
            FROM    dbo.CARI_HESAP_HAREKETLERI chh2
            WHERE   chh2.cha_normal_Iade = 1 
            GROUP BY chh2.cha_kod
        ) chh2
            ON chh2.cha_kod = ch.cari_kod;

这甚至可能不需要子查询,但正如我所说,如果没有完整的查询,我只能推测你的表格结构,以及你真正想要的结果。

要回答1是,UDF执行比执行相同操作的子查询更糟糕是正常的。当我搜索This answer

时,主题上有很多帖子SQL-Server UDF versus subquery是google的顶部