我需要修复以下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的程序来设计报表布局,但我不是很习惯。因此,如果可以在查询中解决问题,那就太棒了!
答案 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 BY
和ORDER 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
同样如此。
假设:EndDate
是date
,我们只需添加integer
::EndDate + 1
si.cancel = 'N'
和sa.cancel = 'N'
看起来像应该真正实现为boolean
的列。
我将ORDER BY
改编为您的说明:
排名将按“产品A”和“产品B”销售
排序
按降序排列NULL值,除非您将其设为DESC NULLS LAST
: