使用SQL迭代匹配数据?

时间:2011-11-23 20:31:36

标签: sql postgresql group-by

我正在努力解决一个问题,而且我已经被困了几天而没有弄清楚这是否可能。

我有如下结果集:

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标记为选中。

我也不能使用存储过程。我开始认为不可能完成,但也许有人可以抛出一点光。

提前致谢!

2 个答案:

答案 0 :(得分:2)

修改

第一个版本没有解决问题。

ordercasereserved words in PostgreSQL。不要将它们用作标识符!在我的示例中,我重命名为ordcas

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最多有两个cascode,其他列不会添加更多变体。 它产生了问题中证明的结果。

答案 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