查询SQL - 使用空值

时间:2015-04-23 20:11:50

标签: sql postgresql aggregate aggregate-filter

我需要修复以下SQL查询:

SELECT  sep.name AS company_name,
    atnp.name AS employee_name,
    (Case WHEN ip.id_item = 0001 THEN 'Product A'  
        ELSE 'Product B'
        END ) AS product_name,
    (Case WHEN ivcp.id_item = 0001 THEN SUM(ivcp.quantity) 
        ELSE NULL
        END ) AS quantityA,
    (Case WHEN ivcp.id_item = 0002 THEN SUM(ivcp.quantity) 
        ELSE NULL
        END ) AS quantityB
FROM    sale_item AS ivcp
    INNER JOIN stock AS mep ON (mep.id_stock = ivcp.id_stock)
    INNER JOIN sale AS vcp ON (vcp.id_sale = ivcp.id_sale)
    INNER JOIN terminal_sale AS mvtp ON (mvtp.id_terminal_sale = vcp.id_terminal_sale)
    INNER JOIN item AS ip ON (ivcp.id_item = ip.id_item)
    INNER JOIN item_category AS cip ON (ip.id_category_item = cip.id_category_item)
    LEFT OUTER JOIN employee AS atnp ON (atnp.id_employee = ivcp.id_employee)
    INNER JOIN sis_company AS sep ON (sep.id_company = mvtp.id_company)
WHERE   mvtp.id_company IN (1)
AND mvtp.date_sale BETWEEN :BeginDate AND  :EndDate
AND DATE(ivcp.date_sale) BETWEEN :BeginDate AND  :EndDate
AND DATE(vcp.data_rec) BETWEEN :BeginDate AND  :EndDate
AND mep.date_sale BETWEEN :BeginDate AND  :EndDate
AND (-1 = -1 OR ivcp.id_employee IN
           (SELECT id_employee FROM team_employee WHERE id_employee = -1))
AND ip.id_category_item = 100
AND ivcp.id_item IN (0002,0001)
AND (ivcp.cancel = 'N' AND vcp.cancel = 'N')
GROUP BY sep.name,
    atnp.name,
    ip.id_item,
    ivcp.id_item
ORDER BY sep.name

结果:

COMPANY   | EMPLOYEE   | PRODUCT NAME | QUANTITY A | QUANTITY B
Company A | Employee A | Product A    | 1.64       | NULL
Company A | Employee A | Product B    | NULL       | 4.70
Company A | Employee B | Product A    | 84.191     | NULL
Company A | Employee B | Product B    | NULL       | 91.885

但我想要这个:

COMPANY   | EMPLOYEE   | QUANTITY A | QUANTITY B
Company A | Employee A | 1.64       | 4.70
Company A | Employee B | 84.191     | 91.885
  • 此查询目标是将某些员工的销售额排在最佳卖家之列。排名将由产品A'订购。和'产品B'销售额(ivcp.quantity,id_item = 0001和id_item = 0002)。

  • 内部联接用于匹配销售日期,项目类别,员工ID,股票等。

我正在使用基于Stimulsoft的程序来设计报表布局,但我不是很习惯。因此,如果可以在查询中解决问题,那就太棒了!

1 个答案:

答案 0 :(得分:0)

它基本上是对查询的简化。在此期间,我修复了其他一些事情:

SELECT sc.name AS company_name
     , em.name AS employee_name
     , SUM((CASE WHEN si.id_item = 0001 THEN si.quantity END) AS quantity_a
     , SUM((CASE WHEN si.id_item = 0002 THEN si.quantity END) AS quantity_b
FROM   team_employee  te
JOIN   sale_item      si USING (id_employee)
JOIN   stock          st ON st.id_stock = si.id_stock
JOIN   sale           sa ON sa.id_sale = si.id_sale
JOIN   terminal_sale  ts ON ts.id_terminal_sale = sa.id_terminal_sale
JOIN   sis_company    sc ON sc.id_company = ts.id_company
JOIN   item           ip ON ip.id_item = si.id_item
JOIN   item_category  ic ON ic.id_category_item = ip.id_category_item
LEFT   JOIN employee  em ON em.id_employee = si.id_employee
WHERE  te.id_employee = -1
AND    st.date_sale BETWEEN :BeginDate AND :EndDate
AND    ts.date_sale BETWEEN :BeginDate AND :EndDate
AND    si.date_sale >= :BeginDate      -- inlude lower border
AND    si.date_sale <  (:EndDate + 1)  -- exclude upper border
AND    sa.data_rec  >= :BeginDate
AND    sa.data_rec  <  (:EndDate + 1)
AND    ts.id_company = 1
AND    ip.id_category_item = 100
AND    si.id_item IN (0002,0001)
AND    si.cancel = 'N'
AND    sa.cancel = 'N'
GROUP  BY 1, 2
ORDER  BY 3 DESC NULLS LAST
        , 4 DESC NULLS LAST;
  • 关于您的问题:使用如下所示的方式恢复方法: CASE语句的总和 而不是反过来说。并相应地调整GROUP BYORDER BY 在Postgres 9.4中,您将使用汇总FILTER

  • -1 = -1 OR ...只是噪音。我删除了它。

  • 很奇怪:

    AND   (ivcp.id_employee IN 
      (SELECT id_employee FROM team_employee WHERE id_employee = -1))
    

    假设-1应该是一个参数。无论哪种方式,我都将其重写为另一个连接。

  • 为什么ip.id_item = 0001中的前导零?如果它是一个数字,则删除零。如果是字符串,请添加单引号,使其成为sting文字,而不是数字文字。

  • id_company IN (1)只是说id_company = 1的一种错综复杂的方式。

  • 为什么演员DATE(si.date_sale)?该名称表明它已经是date。该名称具有误导性或表达方式。无论哪种方式,这都不利于性能,因为表达式不是sargable 假设它是timestamp我改写它是可以理解的。与sa.data_rec同样如此。 假设:EndDatedate,我们只需添加integer:EndDate + 1

  • si.cancel = 'N'sa.cancel = 'N'看起来像应该真正实现为boolean的列。

  • 我将ORDER BY改编为您的说明:

      

    排名将按“产品A”和“产品B”销售

    排序

    按降序排列NULL值,除非您将其设为DESC NULLS LAST