我在Greenplum工作 - postgresql DB并且具有以下数据结构:
在此我需要以下逻辑来实现(其中一些我已经实现过):
CASE WHEN PDATE IS NOT NULL THEN to_char(PDATE,'YYYY-MM-DD')
WHEN PDATE IS NULL THEN to_char(NDATE,'YYYY-MM-DD N')
WHEN NDATEIS NULL THEN 'NO PO' ELSE 'NO PO' END
根据我需要QTY和VName。
数量:根据min(PDATE和NDATE)得出的总和(数量)
VName:VName根据min(PDATE和NDATE)
期望的输出:
到目前为止,我已经在下面进行了查询:
SELECT
ITEM ,
MIN(CASE WHEN PDATE IS NOT NULL THEN to_char(PDATE,'YYYY-MM-DD')
WHEN PDATE IS NULL THEN to_char(NDATE,'YYYY-MM-DD N')
WHEN NDATE IS NULL THEN 'NO PO' ELSE 'NO PO' END) AS PRO
FROM
Table
GROUP BY
ITEM
请帮我解决问题
答案 0 :(得分:1)
感谢蒂姆的帮助..我花了一些时间来创建查询,但最后它已经完成了..为了节省时间我在论坛中发布了这个问题,结束了同样的事情 - 花了时间。
这里是查询
SELECT
FO.ID ,
(CASE WHEN FO.DateQ IS NOT NULL THEN to_char(FO.DateQ ,'YYYY-MM-DD')
WHEN FO.DateQ IS NULL THEN to_char(FO.Datew ,'YYYY-MM-DD N')
WHEN FO.Datew IS NULL AND FO.DateQ IS NULL THEN 'NO PO' END) AS DATER ,
FO.QTY ,
FO.VNAME
FROM
(
SELECT
NT.ID ,
PT.DATEQ ,
PT.DATEW ,
SUM(NT.QTY) AS QTY ,
array_to_string(array_agg(NT.VNAME) ,', ') AS VNAME
FROM
TABLENAME NT INNER JOIN(
SELECT
AST.ID ,
AST.DateQ ,
(CASE WHEN AST.DateQ IS NULL THEN AST.DateW ELSE NULL END) AS DateW
FROM
(
SELECT
ID ,
MIN(PDATE) AS DATEQ ,
MIN(CASE WHEN pdate IS NULL THEN ndate END) DATEW
FROM
TABLENAME
GROUP BY
ID
) AST
) PT
ON NT.ID = PT.ID
AND NT.PDATE = PT.DATEQ
OR NT.NDATE = PT.DATEW
GROUP BY
NT.ID ,
PT.DATEQ ,
PT.DATEW
) FO
ORDER BY
FO.ID
将ID视为项目。
答案 1 :(得分:0)
以下答案假设您使用的是Postgres版本8.4或更高版本,它附带了一个名为ARRAY_AGG()
的聚合函数。我使用ARRAY_AGG()
为每个VNAME
- ITEM
群组MIN(DATE)
创建以逗号分隔的列表。
SELECT t1.ITEM, t1.DATE, t1.QTY, t1.VNAME
FROM
(
SELECT t.ITEM, t.DATE AS DATE, SUM(t.QTY) AS QTY, ARRAY_AGG(VNAME) AS VNAME
FROM
(
SELECT t.ITEM, LEAST(t.PDATE, t.NDATE) AS DATE, t.QTY, t.VNAME
FROM Table t
) t
GROUP BY t.ITEM, t.DATE
) t1
INNER JOIN
(
SELECT t.ITEM, MIN(LEAST(t.PDATE, t.NDATE)) AS DATE
FROM Table t
GROUP BY t.ITEM
) t2
ON t1.ITEM = t2.ITEM AND t1.PDATE = t2.PDATE
<强>解释强>
第一个查询获取每个QTY
- VNAME
组合的ITEM
总和和PDATE
CSV聚合。但是,您只需要每个组中最早日期的聚合。第一个查询加入的第二个查询会过滤掉不需要的组,从而为您提供所需的结果。
由于您使用的是Postgres 8.2,因此您必须定义自己的自定义函数:
CREATE AGGREGATE ARRAY_AGG (anyelement)
(
sfunc = array_append,
stype = anyarray,
initcond = '{}'
);
答案 2 :(得分:0)
Anshul,您的解决方案可以正常工作,但是当您加入桌面两次时会出现性能损失,这会迫使数据库扫描您的表两次。更好的解决方案是使用分析函数,只引用一次表。
以下是一个例子:
CREATE TABLE anshul
(
item character varying,
pdate date,
ndate date,
qty integer,
vname character varying
)
WITH (APPENDONLY=true)
DISTRIBUTED BY (item);
INSERT INTO ANSHUL VALUES
('ABC', NULL, '2015-12-31', 10, 'Y JACK SOLLEN'),
('HRD', '2016-01-29', '2016-1-8', 5, 'H HARRIS'),
('HRD', '2015-09-07', '2015-10-09', 31, 'G JOE'),
('HRD', '2015-09-30', '2015-09-07', 28, 'K KAMATH'),
('GGT', '2015-12-10', '2015-12-12', 10, 'P QUIK'),
('GGT', '2015-12-27', NULL, 20, NULL),
('GGT', '2015-12-10', '2016-01-04', 22, 'U RITZ'),
('GGT', '2016-01-07', '2016-01-07', 22, 'S SUE DAL'),
('OWE', NULL, '2015-12-22', 6, 'J JASON NIT'),
('OWE', NULL, '2015-11-05', 2, 'P QUEER'),
('OWE', NULL, '2015-11-05', 5, 'K KITTAN');
这是一个查询借用了你已经想到的一些代码。
SELECT item,
sum(qty) AS qty,
array_to_string(array_agg(vname), ',') AS vname
FROM (
SELECT item,
rank() OVER(PARTITION BY item ORDER BY desired_date) AS rank,
qty,
vname
FROM (SELECT item,
qty,
vname,
CASE WHEN PDATE IS NOT NULL THEN pdate
WHEN PDATE IS NULL THEN ndate END AS desired_date
FROM anshul
) AS sub1
) AS sub
WHERE sub.rank = 1
GROUP BY item
ORDER BY item;
结果:
item | qty | vname
------+-----+------------------
ABC | 10 | Y JACK SOLLEN
GGT | 32 | P QUIK,U RITZ
HRD | 31 | G JOE
OWE | 7 | K KITTAN,P QUEER