【问题标题】:Match data iteratively with SQL?用 SQL 迭代匹配数据?
【发布时间】:2011-11-23 20:31:35
【问题描述】:

我正在为一个查询而苦苦挣扎,我已经被困了好几天了,根本不知道这是否可能。

我有如下结果集:

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

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

提前致谢!

【问题讨论】:

  • 对不起,但我不明白“CASE 2710 需要与不同的 LINE 匹配”是什么意思。 2710 与第 1 行、第 2 行和第 3 行相关联,您希望它带回 1 或 3 而不是带回 2?为什么??
  • 将其翻译为:我只想要 (case, line) 的唯一组合是否公平?
  • @Julien,我不想与 2 匹配,因为 CODE 为空。我希望 2708 与 1 或 3 匹配,而 2710 与其他可能性匹配。
  • @ErwinBrandstetter,不确定。最初我有四个独特的组合,不是吗? [(2710,1), (2710,3), (2708,1), (2708,3)] 我需要想出 [(2710,1), (2708,3)] 或 [(2710, 3), (2708,1)]

标签: sql postgresql group-by


【解决方案1】:

编辑

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

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;

这假设每个code 最多有两个不同的linecas,并且其他列不会添加更多变体。 它产生了问题中展示的结果。

【讨论】:

  • 这将产生 cas(2708,2710) 和 line(1,3) 的所有 4 种组合 - OP 说过他只想要 2 个具有互补值的组合,即。 2708,1 和 2710,3,或 2708,3 和 2710,1。
  • @Mark:我在未决的澄清请求中回答了。但是现在您指出了这一点,我很清楚 OP 想要什么。很快会修改我的答案,谢谢。 (编辑清理。)
  • 是否可以扩展N个不同行或cas per code的情况?
  • @Gothmog:使用n &gt; 2,您需要更复杂的解决方案。您需要准确定义问题。从示例来看,这个问题针对的是成对的值 (n = 2)。如果您想要n &gt; 2,我建议您使用准确的描述开始一个新问题。使用纯 SQL 可以实现很多事情,但它会变得非常复杂。根据问题的实际定义,plpgsql 函数可能是更简单/更快的解决方案。
【解决方案2】:

以下将产生与指定相同的输出,但尚不清楚您的数据是否总是按 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

【讨论】:

    猜你喜欢
    • 2014-02-19
    • 2011-12-16
    • 2011-12-28
    • 2018-04-06
    • 2021-09-15
    • 1970-01-01
    • 2019-06-25
    • 2016-12-29
    • 1970-01-01
    相关资源
    最近更新 更多