【问题标题】:Oracle SQL merge half empty query linesOracle SQL 合并半空查询行
【发布时间】:2023-01-20 18:38:05
【问题描述】:

我有一个 Oracle12 和一张表

Debit Credit
a1 b1
c1 a1
c2 a1
b2 a2
a2 b3
a2 c2

没有包含 a%+a%b%+b% 的行

我想选择 4 列:Debit+Credit 任何列中都存在 a% and not b%Debit+Credit在任何列中存在a% and b%。第一列对必须对应第二对 a% 值。

就像是

with t as (
  select 'a1' Debit, 'b1' Credit from dual
  union all select 'c1', 'a1' from dual
  union all select 'c2', 'a1' from dual
  union all select 'b2', 'a2' from dual
  union all select 'a2', 'b3' from dual
  union all select 'a2', 'c2' from dual)
select Debit, Credit, null DebitB, null CreditB
    from t
    where (Debit like 'a%' or Credit like 'a%')
    and (Debit not like 'b%' and Credit not like 'b%')
    union all
    select null, null, Debit, Credit
    from t
    where (Debit like 'a%' or Credit like 'a%')
    and (Debit like 'b%' or Credit like 'b%')

但将这 6 行合并(如果可能,排除空单元格)为 4 行,由 a%“分组”。首先,所有合并行都带有a1,然后所有合并行都带有a2,依此类推。组内的任何顺序,最后为空。结果必须是

Debit Credit DebitB CreditB
c1 a1 a1 b1
c2 a1
a2 c2 b2 a2
a2 b3

【问题讨论】:

  • 如果源表中有(a1, a2)行怎么办?为什么 (a1 b1)(c1 a1) 合并,而不是 (c2 a1)
  • 没有行 (a, a)(b, b),组内的任何顺序,空值最后

标签: sql oracle


【解决方案1】:

您可以对行进行编号并使用 FULL OUTER JOIN 匹配 a 值和行号:

SELECT t1.Debit,
       t1.Credit,
       t2.debit  AS DebitB,
       t2.credit AS CreditB
FROM   (
         SELECT t.*,
                ROW_NUMBER() OVER (
                  PARTITION BY CASE WHEN debit LIKE 'a%' THEN debit ELSE credit END
                  ORDER BY CASE WHEN debit LIKE 'a%' THEN credit ELSE debit END
                ) AS rn
         FROM   t
         WHERE  debit LIKE 'a%' AND credit NOT LIKE 'b%'
         OR     debit NOT LIKE 'b%' AND credit LIKE 'a%'
       ) t1
       FULL OUTER JOIN (
         SELECT t.*,
                ROW_NUMBER() OVER (
                  PARTITION BY CASE WHEN debit LIKE 'a%' THEN debit ELSE credit END
                  ORDER BY CASE WHEN debit LIKE 'a%' THEN credit ELSE debit END
                ) AS rn
         FROM   t
         WHERE  debit LIKE 'a%' AND credit LIKE 'b%'
         OR     debit LIKE 'b%' AND credit LIKE 'a%'
       ) t2
       ON (  t1.debit = t2.credit  AND t1.credit != t2.debit
          OR t1.debit != t2.credit AND t1.credit =  t2.debit )
          AND t1.rn = t2.rn

其中,对于示例数据:

CREATE TABLE t (debit, credit) as
  select 'a1', 'b1' from dual union all
  select 'c1', 'a1' from dual union all
  select 'c2', 'a1' from dual union all
  select 'b2', 'a2' from dual union all
  select 'a2', 'b3' from dual union all
  select 'a2', 'c2' from dual;

输出:

DEBIT CREDIT DEBITB CREDITB
c1 a1 a1 b1
a2 c2 b2 a2
null null a2 b3
c2 a1 null null

fiddle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 2016-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多