两个快速查询,合并时速度慢

时间:2019-08-03 14:05:15

标签: sql sql-server

我有一个庞大的查询,我想向其中添加左联接。 添加的内容已被注释掉。

主查询运行<4秒,32,000行。
注释的部分运行时间少于1秒,共51,000行。

但是,当我将它们组合在一起时,即加入第二个查询,整个过程将在15秒内完成。

原始查询中已经有2个大规模联接(均为50,000行),所以我不知道为什么这种联接很特殊。

PS:我可能还在做其他次优的事情,请批评。

select 
    *,
    case 
        when t2.status = 1 and t2.price > t2.buyprice then round((t2.price - t2.buyprice) * 0.04, 2)
        when t2.status = 2 and t2.price > t2.buyprice then round((t2.price - t2.buyprice) * 0.03, 2)
        when t2.status = 3 and t2.price > t2.buyprice then round((t2.price - t2.buyprice) * 0.02, 2)
        when t2.status = 4 and t2.price > t2.buyprice then round((t2.price - t2.buyprice) * 0.01, 2)
        else 0
    end as bonus
from (
    select *,
        case 
            when t1.gratis = 1 then 10
            when t1.price_vat = 0 or t1.price = 0 then
                case 
                    when t1.stock > 0 or soldLast180DaysQty > 0 then -1
                    when t1.stock = 0 then 12
                end
            when t1.buyprice = 0 then
                case
                    when t1.stock > 0 then -1
                    when t1.stock = 0 then 12
                end
            when soldLast180DaysQty < 0 then 1
            when t1.age_days < 60 then 9
            when t1.last_import <= 180 then
                case
                    when t1.soldLast180DaysQty <= t1.stock then 0
                    when t1.soldLast180DaysQty > t1.stock then 7
                    when t1.stock = 0 then 5
                end
            when t1.last_import >= 180 and t1.stock = 0 then
                case
                    when soldLast180DaysQty > 0 then 10
                    when soldLast180DaysQty = 0 then 11
                end
            when t1.last_import >= 180 then 
                case
                    when t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) < 0.3 and t1.stock_retail / t1.stock >= 0.9 then 5 
                    when t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) between 0 and 0.1 then 1
                    when t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) between 0.1 and 0.2 then 2
                    when t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) between 0.2 and 0.3 then 3
                    when t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) between 0.3 and 0.4 then 4
                    when t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) between 0.4 and 0.7 then 0
                    when t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) >= 0.9 then 6
                    when t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) between 0.8 and 0.9 then 7
                    when t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) between 0.7 and 0.8 then 8
                end
        end as status,
        round(t1.soldLast180DaysQty / nullif(t1.stock + t1.soldLast180DaysQty, 0) * 100, 0) as ratio
    from (
        select
            si.anqid id,
            CAST(rtrim(si.acident) as nvarchar(7)) as code,
            CAST(rtrim(si.acname) as nvarchar(100)) as name,
            si.anvat as vat,
            si.ansaleprice as price_vat,
            round(si.anrtprice, 2) as price,

            cenovnik.clientPrice,  -- <---------------------- This part

            round(si.anbuyprice, 2) as buyprice,
            concat(round(anpricesupp, 2), ' ', acpurchcurr) as fakturna,
            round(si.anrtprice - si.anbuyprice, 2) as profit,
            case
                when si.anrtprice is not null and si.anrtprice > 0 and si.anbuyprice is not null and si.anbuyprice > 0
                then round((si.anrtprice / si.anbuyprice - 1) * 100, 0)
            end as margin,
            cast(si.acfieldsa as nvarchar(12)) as [group],
            cast(rtrim(si.acClassif2) as nvarchar(16)) as category,
            cast(rtrim(ss.acsubject) as nvarchar(7)) as supplier_code,
            cast(left(ss.acname2, 30) as nvarchar(30)) as supplier_name,
            rtrim(si.acclassif) as rebate,
            si.anFieldNA as webActive,
            si.anfieldNF as gratis,
            case
                when si.acpicture is not null then 'true'
                else 'false'
            end as picture,
            isnull((select sum(anstock) from the_stock where acident = si.acident and acwarehouse = '00051'), 0) as stock_warehouse,
            isnull((select sum(anstock) from the_stock where acident = si.acident and acwarehouse <> '00051'), 0) as stock_retail,
            isnull((select sum(anstock) from the_stock where acident = si.acident), 0) as stock,
            isnull((select sum(anReserved) from the_stock where acident = si.acident), 0) as stock_reserved,
            isnull((select sum(anvalue) from the_stock where acident = si.acident), 0) as stock_value,
            (
                select isnull(datediff(day, max(m.addate), getdate()), 9999)
                    from the_moveitem mi
                        left join the_move m
                            on mi.ackey = m.ackey
                    where mi.acident = si.acident and m.acDocType in ('1900', '1000', '6800', '1A00')
            ) as last_import,
            isnull(round(soldLast180Days.soldLast180DaysQty, 0), 0) soldLast180DaysQty,
            isnull(round(soldLast180Days.soldLast180DaysCogs, 0), 0) soldLast180DaysCogs,
            isnull(round(soldLast180Days.soldLast180DaysRevenue, 0), 0) soldLast180DaysRevenue,
            isnull(round(soldLast180Days.soldLast180DaysProfit, 0), 0) soldLast180DaysProfit,
            datediff(day, si.adtimeins, getdate()) as age_days
        from the_setitem si


            /*
            left join (
                SELECT
                    si.acident sku,
                    case
                        when dogovoren.anPrice is null and matrica.anRebate is null then si.anRTPrice
                        when dogovoren.anPrice is not null then dogovoren.anPrice
                        when dogovoren.anPrice is null then si.anRTPrice * (1 - matrica.anRebate/100)
                    end as clientPrice
                FROM tHE_SetItem si
                    left join (
                        select acident, anPrice 
                        from vHE_SetSubjPriceItemExtToday 
                        where acsubject = '1111'
                    ) dogovoren
                        on dogovoren.acident = si.acident
                    left join (
                        select acClassif, anRebate 
                        from vHE_SetSubjTypePriceCateg 
                        where acSubjType = (select acsubjtypebuyer from tHE_SetSubj where acsubject = '1111')
                    ) matrica
                        on si.acClassif = matrica.acClassif
            ) cenovnik
                on cenovnik.sku = si.acident
            */


            left join tHE_SetSubj ss
                on ss.acsubject = si.acsupplier
            left join (
                select 
                    mi.acident, 
                    sum(mi.anQty) soldLast180DaysQty,
                    sum(mi.anQty * mi.anStockPrice) soldLast180DaysCogs,
                    sum(mi.anPVVATBase) soldLast180DaysRevenue,
                    sum(mi.anPVVATBase - mi.anQty * mi.anStockPrice) soldLast180DaysProfit
                from the_moveitem mi
                    left join the_move m
                        on m.ackey = mi.ackey
                where m.acDocType in ('3000', '3050', '3190', '3800', '3550', '3X10', '3950', '3500', '3510', '6700', '3A00', '3210', '3220', '3230', '3240', '3450', '3250', '3260', '3270', '3540', '3460', '3280', '3290', '3310', '3320', '3440', '3330', '3340', '3350', '3360', '3370', '3380', '3390', '3410', '3470', '3420', '3430', '3480', '3490', '3520', '3530', '3560', '3610', '2540', '2740', '2730'
                ) and m.addate >= getdate() - 180
                group by mi.acident
            ) soldLast180Days
                on soldLast180Days.acIdent = si.acident
        ) t1
) t2
where 
    t2.status < 11
order by 
    t2.status asc,
    t2.stock_value desc

如果相关,我正在使用SQL Server。

1 个答案:

答案 0 :(得分:1)

并不是一个真正的答案-但是当我遇到这个问题时,我只是创建了临时表。在SQL Server中,为表名加上#前缀,会话结束后它们将被删除。

您可能将嵌套表t1理解为临时表#t1

CREATE TABLE #t1 (id INT, code NVARCHAR(7), etc...)
INSERT INTO #t1
    select
        si.anqid id,
        CAST(rtrim(si.acident) as nvarchar(7)) as code,
        CAST(rtrim(si.acname) as nvarchar(100)) as name,
        etc..
SELECT * FROM ....  #t1 ...

将所有对t1的引用替换为#t1