Oracle SQL 使用 CTE 在同一行上获取值

Oracle SQL get values on the same row using CTE

我有一个小tablebalance:

TYPE    BNO    AMT
DEB-AA  1111   50
CRED-AA 2222   -50
CRED-AA 3333   -20
DEB-AA  4444   20

目前我的输出是这样的:

DEBNUM        DEBAMT   CREDNUM       CREDAMT
DEB-AA 1111   50       NULL          NULL
NULL          NULL     CRED-AA 2222  -50
NULL          NULL     CRED-AA 3333  -20
DEB-AA 4444   20       NULL          NULL

来自这个查询:

SELECT 
CASE WHEN SUBSTR(TYPE, 1, 3) = 'DEB' THEN TYPE||' '|| BNO ELSE NULL END AS "DEBNUM",
CASE WHEN SUBSTR(TYPE, 1, 3) = 'DEB' THEN AMT ELSE NULL END AS "DEBAMT",
CASE WHEN SUBSTR(TYPE, 1, 4) = 'CRED' THEN TYPE||' '|| BNO ELSE NULL END AS "CREDNUM",
CASE WHEN SUBSTR(TYPE, 1, 4) = 'CRED' THEN AMT ELSE NULL END AS "CREDAMT"
FROM balance

我希望我的输出看起来像这样:

DEBNUM        DEBAMT   CREDNUM       CREDAMT
DEB-AA 1111   50       CRED-AA 2222  -50
DEB-AA 4444   20       CRED-AA 3333  -20

现在我认为它需要一个 CTE,但我无法 运行 得到它,因为我没有那么多创建它们的经验。

编辑

当将此引入到没有 CRED 和 DEB 的较大数据集时,它会正确地拉回数据。但它没有链接同时具有 deb 和 cred 值的行。例如

当前输出:

DEBNUM        DEBAMT   CREDNUM       CREDAMT
DEB-AA 6666   80       CR-QS 2222   -50
DEB-AA 5555   150      CR-QS 4444   -20
DEB-AA 7777   70        
DEB-AA 8888   200       
DEB-AA 9999   60    
DEB-AA 1111   50    
DEB-AA 3333   20        

期望的输出:

DEBNUM        DEBAMT   CREDNUM       CREDAMT
DEB-AA 1111   50       CR-QS 2222   -50
DEB-AA 3333   20       CR-QS 4444   -20
DEB-AA 7777   70       NULL         NULL
DEB-AA 8888   200      NULL         NULL
DEB-AA 9999   60       NULL         NULL
DEB-AA 6666   80       NULL         NULL
DEB-AA 5555   150      NULL         NULL

现在我认为这可以通过使用将 CRED 链接到 DEB 的额外字段来实现。这是更新的示例数据:

TYPE    BNO   AMT  DEBBNO
DEB-AA  1111  50   NULL
CRED-AA 2222  -50  1111
CRED-AA 3333  -20  4444
DEB-AA  4444  20   NULL
DEB-AA  7777  70   NULL
DEB-AA  8888  200  NULL
DEB-AA  9999  60   NULL 
DEB-AA  6666  80   NULL  
DEB-AA  5555  150  NULL

数据:

CREATE TABLE balance(
   TYPE VARCHAR(18) NOT NULL 
  ,BNO  INTEGER  NOT NULL
  ,AMT  INTEGER  NOT NULL
);
INSERT INTO balance(TYPE,BNO,AMT) VALUES ('DEB-AA',1111,50);
INSERT INTO balance(TYPE,BNO,AMT) VALUES ('CRED-AA',2222,-50);
INSERT INTO balance(TYPE,BNO,AMT) VALUES ('CRED-AA',3333,-20);
INSERT INTO balance(TYPE,BNO,AMT) VALUES ('DEB-AA',4444,20);

查询:

WITH deb AS
(
  SELECT 
     TYPE || ' ' ||  BNO AS DEBNUM
    ,AMT AS DEBAMT
    ,ROW_NUMBER() OVER(ORDER BY BNO ASC) AS rn
  FROM balance
  WHERE TYPE LIKE 'DEB%'
), cred AS
(
  SELECT 
     TYPE || ' ' ||  BNO AS CREDNUM
    ,AMT AS CREDAMT
    ,ROW_NUMBER() OVER(ORDER BY BNO ASC) AS rn
  FROM balance
  WHERE TYPE LIKE 'CRED%'
)
SELECT d.DEBNUM, d.DEBAMT, c.CREDNUM, c.CREDAMT
FROM deb d
JOIN cred c
  ON d.rn = c.rn;

SqlFiddle Demo

请记住,如果 table 包含不同数量的 DEB/CRED,您可能需要 FULL OUTER JOIN

编辑:

WITH deb AS
(
  SELECT 
     TYPE || ' ' ||  BNO AS DEBNUM
    ,AMT AS DEBAMT
    ,BNO
  FROM balance
  WHERE TYPE LIKE 'DEB%'
), cred AS
(
  SELECT 
     TYPE || ' ' ||  BNO AS CREDNUM
    ,AMT AS CREDAMT
    ,DEBBNO
  FROM balance
  WHERE TYPE LIKE 'CRED%'
)
SELECT d.DEBNUM, d.DEBAMT, c.CREDNUM, c.CREDAMT
FROM deb d
LEFT JOIN cred c
  ON d.BNO = c.DEBBNO;

SqlFiddleDemo2