我正在努力解决一个问题,而且我已经被困了几天而没有弄清楚这是否可能。
我有如下结果集:
ID ;CASE;LINE;QTY;ORDER;CODE
1446;2725; 1; 1;33333;A
1446;2724; 1; 1;33333;A
0430;2545; 1; 2;44444;B
0430;2547; 1; 2;44444;B
9628;2710; 1; 1;55555;C
9628;2708; 1; 1;55555;C
9628;2708; 2; 1;66666;
9628;2710; 2; 1;66666;
9628;2710; 3; 1;55555;C
9628;2708; 3; 1;55555;C
从这些方面来说,我想得到这些:
1446;2725; 1; 1;33333;A
1446;2724; 1; 1;33333;A
0430;2545; 1; 2;44444;B
0430;2547; 1; 2;44444;B
9628;2710; 1; 1;55555;C
9628;2708; 3; 1;55555;C
或者:
1446;2725; 1; 1;33333;A
1446;2724; 1; 1;33333;A
0430;2545; 1; 2;44444;B
0430;2547; 1; 2;44444;B
9628;2708; 1; 1;55555;C
9628;2710; 3; 1;55555;C
,即我想过滤掉那些CODE为null的(我可以这样做),并希望将案例与行匹配(这是我遇到问题的地方)。
问题在于我与歧视没有任何关系。 CASE 2708与LINE 3或1匹配无关紧要,但CASE 2710需要与不同的LINE匹配。
在Java或C ++这样的语言中这很容易,但由于我不能声明变量或列表,我不知道如何将LINE标记为选中。
我也不能使用存储过程。我开始认为不可能完成,但也许有人可以抛出一点光。
提前致谢!
答案 0 :(得分:2)
第一个版本没有解决问题。
order
和case
是reserved words in PostgreSQL。不要将它们用作标识符!在我的示例中,我重命名为ord
和cas
。
WITH x AS (
SELECT id, qty, ord, code
,min(line) AS line1
,max(line) AS line2
,min(cas) AS cas1
,max(cas) AS cas2
FROM tbl
WHERE code IS NOT NULL
GROUP BY 1,2,3,4
)
SELECT id, cas1, line2, qty, ord, code
FROM x
UNION ALL -- only add more rows, where
SELECT id, cas2, line1, qty, ord, code
FROM x
WHERE cas1 <> cas2 AND line1 <> line2
ORDER BY code, 1,2,3,4,5;
这假定每个line
最多有两个cas
或code
,其他列不会添加更多变体。
它产生了问题中证明的结果。
答案 1 :(得分:1)
以下将生成与指定相同的输出,但不清楚您的数据是否始终按ID生成值对:
SELECT ID,
CASE M.AGG WHEN "MIN" THEN MIN(M."CASE")
ELSE MAX(M."CASE")
END AS "CASE",
CASE M.AGG WHEN "MIN" THEN MIN(M.LINE)
ELSE MAX(M.LINE)
END AS LINE,
CASE M.AGG WHEN "MIN" THEN MIN(M.QTY)
ELSE MAX(M.QTY)
END AS QTY,
CASE M.AGG WHEN "MIN" THEN MIN(M."ORDER")
ELSE MAX(M."ORDER")
END AS "ORDER",
CASE M.AGG WHEN "MIN" THEN MIN(M."CODE")
ELSE MAX(M."CODE")
END AS "CODE"
FROM MYTABLE M
CROSS JOIN (SELECT "MIN" AGG UNION SELECT "MAX") A
WHERE M.CODE IS NOT NULL
GROUP BY M.ID, A.AGG