sql优化

 SQL server 数据库里 写了一个sql  最后的数据集 执行出来 需要 很长时间 三四分钟 其实 就只有 8000多条数据  请大佬看一下 这个 sql 可不可以优化一下 提高一下 查询效率



--静态表处理 多列变成一列 抛出大类

WITH GA AS (SELECT DISTINCT DESIGNKCODE,BEXTSTR1 AS EXTSTR1,YEAR,BIG_TYPE,mc_fl1,COST FROM DW_product020 WHERE BEXTSTR1 IS NOT NULL        
         UNION
            SELECT DISTINCT DESIGNKCODE,VEXTSTR1,YEAR,BIG_TYPE,mc_fl1,COST FROM DW_product020 WHERE VEXTSTR1 IS NOT NULL  
            UNION
         SELECT DISTINCT DESIGNKCODE,CEXTSTR1,YEAR,BIG_TYPE,mc_fl1,COST FROM DW_product020 WHERE CEXTSTR1 IS NOT NULL 
         ),

--九光档案表处理

     GB AS (
         SELECT DISTINCT designkcode,ExtStr1,BM ,klengthnm as 'YEAR',CAST(ISNULL(DJ_PF1,0) AS DECIMAL(18,2)) AS Kcost,PP,MC_FL1 FROM DW_BoolProductsFile WHERE MC_SPFL2 <> '未通过'
   AND PP IN ('芭欧','ANAN','MIX GEORA','VY','薇薇卡','小侨(jofay)')
   AND MC_FL1 <> '样衣'
   AND MC_FL1 NOT LIKE '%男装%'
   AND MC_FL1 <> '礼品'
   AND MC_FL1 <> '其他'                                          
   AND BM <> 'V16XA1062'
   ),

--找出 档案表中 顶层码一样 成本不一样的数据

     GC AS (SELECT
            T1.DESIGNKCODE,
            T1.EXTSTR1,
   T1.BM,
            T1.YEAR,
   T1.KCOST,
   T1.PP,
   T1.MC_FL1
            FROM GB T1 JOIN GB T2
   ON T1.DESIGNKCODE = T2.DESIGNKCODE AND T1.KCOST <> T2.KCOST
   ),

--在总表过滤掉 顶层码一样 成本不一样的数据

     GD AS (SELECT * FROM GB WHERE DESIGNKCODE NOT IN (SELECT DISTINCT DESIGNKCODE FROM GC)),

--将 顶层码一样 成本不一样的这部分 数据 不一样的成本 取最小值  

     GE AS (select a.DESIGNKCODE ,a.EXTSTR1,a.bm,a.YEAR,b.Mcost as kcost,a.pp,a.MC_FL1
         from GC a
            left join (select distinct DESIGNKcode AS DESIGNKCODE_I , min(Kcost) Mcost from GC group by DESIGNKcode)  b
         on a.DESIGNKCODE=b.DESIGNKcode_I
   ),

--将以过滤的数据 与 源数据放到一起

     GF AS (SELECT * FROM GD
            UNION
            SELECT * FROM GE
            UNION
            SELECT * FROM GB WHERE DESIGNKCODE IS NULL),

--静态表 与 档案表 表关联

     GG AS (SELECT GF.designkcode AS DESIGNKCODE_I,GF.ExtStr1 AS EXTSTR1_I,GF.YEAR AS YEAR_I,GF.MC_FL1 AS MC_FL1_I,GF.Kcost,GA.designkcode,GA.ExtStr1,GA.YEAR,GA.MC_FL1,GA.COST FROM
            GF LEFT JOIN GA
            ON GF.DESIGNKCODE =GA.DESIGNKCODE AND GF.ExtStr1 =GA.ExtStr1
   ),

--过滤掉静态表designkcode为空的数据 

     GH AS (SELECT * FROM GG WHERE DESIGNKCODE IS NOT NULL),

--静态表DESIGNKCODE为空的所有档案表的数据                                         第一部分的模块

     GI AS (SELECT DESIGNKCODE_I AS DESIGNKCODE,EXTSTR1_I AS EXTSTR1,YEAR_I AS YEAR,MC_FL1_I MC_FL1,KCOST AS COST FROM GG WHERE DESIGNKCODE IS NULL),

--静态表 没有关联上 档案表的数据(档案表所有的数据已经关联进去了)                  第二部分的模块

     GJ AS (SELECT DESIGNKCODE,EXTSTR1,YEAR,MC_FL1,COST FROM GA WHERE NOT EXISTS (
      SELECT DISTINCT DESIGNKCODE FROM GG WHERE EXISTS (SELECT DISTINCT DESIGNKCODE FROM GA))),

--顶层码一致 但是 成本不一致的数据

     GK AS (
            SELECT
            T1.DESIGNKCODE_I,
            T1.EXTSTR1_I,
            T1.YEAR_I,
            T1.MC_FL1_I,
   T1.KCOST,
   T1.DESIGNKCODE,
   T1.EXTSTR1,
   T1.YEAR,
   T1.MC_FL1,
   T1.COST
            FROM GH T1 JOIN GH T2
   ON T1.DESIGNKCODE_I = T2.DESIGNKCODE AND T1.KCOST <> T2.COST
            ),

--将成本不同的数据 以 GB的成本 为标准同化GA的成本数据

     GL AS (SELECT *,(CASE WHEN KCOST <> COST THEN KCOST ELSE COST END) AS COST_I FROM GK),

--取出以GB成本为标准的数据                                                       第三部分的模块                         

     GM AS (SELECT DESIGNKCODE_I AS DESIGNKCODE,EXTSTR1_I AS EXTSTR1,YEAR_I AS YEAR,MC_FL1_I AS MC_FL1,KCOST AS COST  FROM GL),

--取出 非 顶层码一致 但是 成本不一致的数据                                       第四部分的模块

     GP AS (select DESIGNKCODE_I AS DESIGNKCODE,EXTSTR1_I AS EXTSTR1,YEAR_I AS YEAR,MC_FL1_I AS MC_FL1,KCOST AS COST FROM GH WHERE DESIGNKCODE_I NOT IN (SELECT DISTINCT DESIGNKCODE_I FROM GK)),

--将前边的几个模块组合

     GQ AS (SELECT * FROM GI
         UNION
         SELECT * FROM GJ
         UNION
         SELECT * FROM GM
         UNION
         SELECT * FROM GP)

   SELECT * FROM GQ


image.png这个结果集 是静态表的designkcode数

image.png

这个 结果集 是 关联的结果集里的 静态表的designkcode数

大哥大没信号 发布于 2020-7-28 16:30 (编辑于 2020-7-29 10:55)
1min目标场景问卷 立即参与
回答问题
悬赏:3 F币 + 添加悬赏
提示:增加悬赏、完善问题、追问等操作,可使您的问题被置顶,并向所有关注者发送通知
共6回答
最佳回答
0
zjc@Lv3初级互助
发布于2020-7-28 18:04

初步优化了一下,肯定比你那个快好几倍,优化的时候最好再参考数据和表结构

--静态表处理 多列变成一列 抛出大类

WITH GA AS

 (SELECT DESIGNKCODE,

                  BEXTSTR1,

                  VEXTSTR1,

                  CEXTSTR1,

                  YEAR,

                  BIG_TYPE,

                  MC_FL1,

                  COST

  FROM   DW_PRODUCT020

  WHERE  BEXTSTR1 IS NOT NULL OR VEXTSTR1 IS NOT NULL OR CEXTSTR1 IS NOT NULL),

--九光档案表处理

GB AS

 (SELECT DISTINCT DESIGNKCODE,

                  EXTSTR1,

                  BM,

                  KLENGTHNM AS 'YEAR',

                  CAST(ISNULL(DJ_PF1, 0) AS DECIMAL(18, 2)) AS KCOST,

                  PP,

                  MC_FL1

  FROM   DW_BOOLPRODUCTSFILE

  WHERE  MC_SPFL2 <> '未通过'

         AND PP IN ('芭欧', 'ANAN', 'MIX GEORA', 'VY', '薇薇卡', '小侨(jofay)')

         AND MC_FL1 <> '样衣'

         AND MC_FL1 NOT LIKE '%男装%'

         AND MC_FL1 <> '礼品'

         AND MC_FL1 <> '其他'

         AND BM <> 'V16XA1062'),

--找出 档案表中 顶层码一样 成本不一样的数据

GC AS

 (SELECT T1.DESIGNKCODE,

         T1.EXTSTR1,

         T1.BM,

         T1.YEAR,

         T1.KCOST,

         T1.PP,

         T1.MC_FL1

  FROM   GB T1

  JOIN   GB T2

  ON     T1.DESIGNKCODE = T2.DESIGNKCODE

         AND T1.KCOST <> T2.KCOST

  WHERE DESIGNKCODE IS NOT NULL),

--在总表过滤掉 顶层码一样 成本不一样的数据

 GD AS

(SELECT   DESIGNKCODE,

                  EXTSTR1,

                  BM,

                  YEAR,

                  KCOST,

                  PP,

                  MC_FL1 

    FROM GB WHERE DESIGNKCODE NOT IN (SELECT DESIGNKCODE FROM GC)

    AND DESIGNKCODE IS NOT NULL),

--将 顶层码一样 成本不一样的这部分 数据 不一样的成本 取最小值  

GE AS

 (SELECT A.DESIGNKCODE,

         A.EXTSTR1,

         A.BM,

         A.YEAR,

         B.MCOST AS KCOST,

         A.PP,

         A.MC_FL1

  FROM   GC A

  LEFT   JOIN (SELECT DESIGNKCODE AS DESIGNKCODE_I,

                              MIN(KCOST) MCOST

              FROM   GC

              GROUP  BY DESIGNKCODE) B

  ON     A.DESIGNKCODE = B.DESIGNKCODE_I),

--将以过滤的数据 与 源数据放到一起

GF AS

 (SELECT * FROM GD UNION ALL SELECT * FROM GE UNION ALL SELECT * FROM GB WHERE DESIGNKCODE IS NULL),

--静态表 与 档案表 表关联

GG AS

 (SELECT GF.DESIGNKCODE AS DESIGNKCODE_I,

         GF.EXTSTR1     AS EXTSTR1_I,

         GF.YEAR        AS YEAR_I,

         GF.MC_FL1      AS MC_FL1_I,

         GF.KCOST,

         GA.DESIGNKCODE,

         COALESCE(GA.BEXTSTR1,VEXTSTR1,CEXTSTR1) EXTSTR1,

         GA.YEAR,

         GA.MC_FL1,

         GA.COST

  FROM   GF

  LEFT   JOIN GA

  ON     GF.DESIGNKCODE = GA.DESIGNKCODE

         AND GF.EXTSTR1 = COALESCE(GA.BEXTSTR1,VEXTSTR1,CEXTSTR1)),

--过滤掉静态表designkcode为空的数据 

GH AS

 (SELECT * FROM GG WHERE DESIGNKCODE IS NOT NULL),

--静态表DESIGNKCODE为空的所有档案表的数据                                         第一部分的模块

GI AS

 (SELECT DESIGNKCODE_I AS DESIGNKCODE,

         EXTSTR1_I     AS EXTSTR1,

         YEAR_I        AS YEAR,

         MC_FL1_I      MC_FL1,

         KCOST         AS COST

  FROM   GG

  WHERE  DESIGNKCODE IS NULL),

--静态表 没有关联上 档案表的数据(档案表所有的数据已经关联进去了)                  第二部分的模块

GJ AS

 (SELECT DESIGNKCODE,

         EXTSTR1,

         YEAR,

         MC_FL1,

         COST

  FROM   GA

  WHERE  NOT EXISTS (SELECT DESIGNKCODE FROM GG WHERE EXISTS (SELECT DESIGNKCODE FROM GA))),

--取出以GB成本为标准的数据                                                       第三部分的模块                         

GM AS

 (SELECT DESIGNKCODE_I AS DESIGNKCODE,

         EXTSTR1_I     AS EXTSTR1,

         YEAR_I        AS YEAR,

         MC_FL1_I      AS MC_FL1,

         KCOST         AS COST

  FROM   GH

  WHERE KCOST<>COST),

--取出 非 顶层码一致 但是 成本不一致的数据                                       第四部分的模块

GP AS

 (SELECT DESIGNKCODE_I AS DESIGNKCODE,

         EXTSTR1_I     AS EXTSTR1,

         YEAR_I        AS YEAR,

         MC_FL1_I      AS MC_FL1,

         KCOST         AS COST

  FROM   GH

  WHERE ISNULL(KCOST,0)=ISNULL(COST,0)),

--将前边的几个模块组合

GQ AS

 (SELECT * FROM GI UNION ALL SELECT * FROM GJ UNION ALL SELECT * FROM GM UNION ALL SELECT * FROM GP)

SELECT * FROM GQ


最佳回答
0
xiaomiliLv6初级互助
发布于2020-7-28 16:31

什么数据库啊,Oracle还是SQL server

最佳回答
0
shirokoLv6资深互助
发布于2020-7-28 16:39

union 和 not in 影响太多。。多重嵌套,感觉是省事从其他地方扒来直接作为子查询,建议从头写


最佳回答
0
时光隧道Lv4见习互助
发布于2020-7-28 16:57


SELECT DISTINCT DESIGNKCODE,BEXTSTR1 AS EXTSTR1,YEAR,BIG_TYPE,mc_fl1,COST FROM DW_product020 WHERE BEXTSTR1 IS NOT NULL         
         UNION 
            SELECT DISTINCT DESIGNKCODE,VEXTSTR1,YEAR,BIG_TYPE,mc_fl1,COST FROM DW_product020 WHERE VEXTSTR1 IS NOT NULL   
            UNION
         SELECT DISTINCT DESIGNKCODE,CEXTSTR1,YEAR,BIG_TYPE,mc_fl1,COST FROM DW_product020 WHERE CEXTSTR1 IS NOT NULL


这种union直接改成where条件不行吗?

最佳回答
0
柠檬不吐酸Lv4见习互助
发布于2020-7-28 17:11

如果是Oracle,多列转成一列可以使用unpivot方法1583149919782072.png

最佳回答
0
jongwangLv6中级互助
发布于2020-7-28 17:11

逻辑上感觉主要部分是顶层码一致和成本不一致的处理重新赋值(前后做了几次),要不整体重新理一下,重写一个

  • 大哥大没信号 大哥大没信号(提问者) 没有 大部分 用在了 区分数据上 目的是为了重新赋值 但是 在那一些数据 需要重新赋值 哪一些不需要 这样的数据分类上 做了好多
    2020-07-28 17:14 
  • jongwang jongwang 回复 大哥大没信号(提问者) 有一种写法对于你要赋值的那一列,case when a.decode=b.decode and a.cost <> b.cost then Min(cost) over (partition by decode order by cost ) else cost end as cost 。这种写法的思路,大概就是比较是否不同,不同的话,则用开窗函数来取最小值,一步到位,不用写group by。不是确切答案,只是探讨一下。。。
    2020-07-28 17:38 
  • 大哥大没信号 大哥大没信号(提问者) 回复 jongwang 这个可以 之前学的开窗函数 都忘光了
    2020-07-29 09:12 
  • 大哥大没信号 大哥大没信号(提问者) 但是 这样去的话 那个 then min (cost) 取得是哪个cost 既然有a b了 应该取a的min(cost) 还是b的min(cost)
    2020-07-29 09:35 
  • jongwang jongwang 回复 大哥大没信号(提问者) 嗯嗯,我想了下,你的逻辑,其实不要a b两个表,只要对于这个表,取最小就行了,是不是这个道理,直接select a.col1,...a.colN, MIN(a.cost) over (partition by decode order by cost) as cost from tablename a因为比如decode只有一行的,那么取最小值本身也没有问题,decode有多行的,取最小值,则是正常我们需要的取的。你觉得呢
    2020-07-29 09:42 
  • 7关注人数
  • 642浏览人数
  • 最后回答于:2020-7-29 10:55
    请选择关闭问题的原因
    确定 取消
    返回顶部