SQL Server 连接多个表而不使用重复行

pbossiut  于 2023-01-08  发布在  其他
关注(0)|答案(1)|浏览(114)

我有3张表,如下所示

CREATE TABLE tbl1 
(
    [ID] [INT]    NULL,
    [Name] [VARCHAR] (50)   NULL
) ;

CREATE TABLE tbl2 
(
    [ID] [INT]    NULL,
    [TranNo] [VARCHAR] (50)   NULL,
    [TranName] [VARCHAR] (50)   NULL  
) ;    

CREATE TABLE tbl3 
(
    [ID] [INT]    NULL,
    [ResultNo] [VARCHAR] (50)   NULL,
    [ResultName] [VARCHAR] (50)   NULL
) ;    

INSERT INTO tbl1 
VALUES (1,'Andy'), (2,'Lisa')

INSERT INTO tbl2 
VALUES (1, 'A1', 'Order'),
       (1, 'A2', 'Order'),
       (1, 'A3', 'Order'),
       (1, 'A4', 'Delivery'),
       (2, 'A5', 'Order'),
       (2, 'A6', 'Delivery'),
       (2, 'A7', 'Delivery')
 
INSERT INTO tbl3
VALUES (1, 'R1', 'Pending'),
       (1, 'R2', 'Success'),
       (2, 'R3', 'Success')

这是我的疑问

Select 
    tbl1.*,
    tbl2.TranNo, tbl2.TranName, 
    tbl3.ResultNo, tbl3.ResultName
from 
    tbl1
left outer join
    tbl2 on tbl1.ID = tbl2.ID
left outer join
    tbl3 on tbl1.ID = tbl3.ID

结果:SQLFIDLE
| 识别号|姓名|运输编号|交易名称|结果编号|结果名称|
| - ------| - ------| - ------| - ------| - ------| - ------|
| 1个|安迪|A1|订单|R1|待定|
| 1个|安迪|A1|订单|R2|成功|
| 1个|安迪|A2|订单|R1|待定|
| 1个|安迪|A2|订单|R2|成功|
| 1个|安迪|A3|订单|R1|待定|
| 1个|安迪|A3|订单|R2|成功|
| 1个|安迪|A4|交付|R1|待定|
| 1个|安迪|A4|交付|R2|成功|
| 第二章|丽莎|A5|订单|R3|成功|
| 第二章|丽莎|A6|交付|R3|成功|
| 第二章|丽莎|A7|交付|R3|成功|
我想要一个无重复结果/无类似的额外结果
| 识别号|姓名|运输编号|交易名称|结果编号|结果名称|
| - ------| - ------| - ------| - ------| - ------| - ------|
| 1个|安迪|A1|订单|R1|待定|
| 1个|安迪|A2|订单|R2|成功|
| 1个|安迪|A3|订单|||
| 1个|安迪|A4|交付|||
| 第二章|丽莎|A5|订单|R3|成功|
| 第二章|丽莎|A6|交付|||
| 第二章|丽莎|A7|交付|||

| 识别号|姓名|运输编号|交易名称|结果编号|结果名称|
| - ------| - ------| - ------| - ------| - ------| - ------|
| 1个|安迪|A1|订单|R1|待定|
| | | A2|订单|R2|成功|
| | | A3|订单|||
| | | A4|交付|||
| 第二章|丽莎|A5|订单|R3|成功|
| | | A6|交付|||
| | | A7|交付|||
谢谢你们中能帮忙的人

wh6knrhe

wh6knrhe1#

看起来像是要通过ID和生成的行号将事务(tbl2)和结果(tbl3)行压缩在一起,然后可以将这些结果与tbl1连接起来。
例如:

;WITH CTE_T AS (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY TranNo) AS RN
    FROM tbl2
),
CTE_R AS (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ResultNo) AS RN
    FROM tbl3
),
CTE_TR AS (
    SELECT
      COALESCE(T.ID, R.ID) AS ID,
      COALESCE(T.RN, R.RN) AS RN,
      T.TranNo, T.TranName, R.ResultNo, R.ResultName
    FROM CTE_T T
    FULL OUTER JOIN CTE_R R
        ON R.ID = T.ID
        AND R.RN = T.RN
)
SELECT A.ID, A.Name, TR.TranNo, TR.TranName, TR.ResultNo, TR.ResultName
FROM tbl1 A
LEFT JOIN CTE_TR TR
    ON TR.ID = A.ID
ORDER BY A.ID, TR.RN

结果:
| 识别号|姓名|运输编号|交易名称|结果编号|结果名称|
| - ------| - ------| - ------| - ------| - ------| - ------|
| 1个|安迪|A1|订单|R1|待定|
| 1个|安迪|A2|订单|R2|成功|
| 1个|安迪|A3|订单|零|零|
| 1个|安迪|A4|交付|零|零|
| 第二章|丽莎|A5|订单|R3|成功|
| 第二章|丽莎|A6|交付|零|零|
| 第二章|丽莎|A7|交付|零|零|
参见this db<>fiddle>
通过用ISNULL(xxx, '') Package 一些结果,可以插入空白来代替空值。
消除重复值最好留给表示层处理,但如果必须这样做,也可以使用检查RN = 1的CASE表达式。请注意,如果要在同一列中包含空值,则需要将ID转换为字符串。
参见this db<>fiddle

相关问题