簡體   English   中英

一對一左連接

[英]One to one left join

如何在每個類別中僅使用一對一行進行左連接。 這是類別ID和產品價格。 請注意,如果我使用LEFT JOIN,我不希望在第5類中出現重復重復。

外適用

(1)最合適的連接是每個表中的類別和價格都匹配。 這是第二類的情況(注意表A和B中的行順序不同)
(2)如果只有類別匹配,那么我想顯示任何行的字段(就像我在第一類中所做的那樣,信息是它是多行之一)。
(3)如果類別和價格都不匹配,我想得到NULL。

我使用了以下查詢,但對我來說太慢了。

with 
A as (select A.id, A.price 
,ROW_NUMBER() over(partition BY id) as Row_id_A
,ROW_NUMBER() OVER(PARTITION BY id, price order by price asc) AS [Row_id_price_A]
from TableA as A)
,
B as (select B.id, B.price, B.field
,ROW_NUMBER() over(partition BY id) as Row_id_B
,ROW_NUMBER() OVER(PARTITION BY id, price order by price asc) AS [Row_id_price_B]
from TableB as B)

select A.id, A.price, A.Row_A, 
,ResultField=case 
    when A.Row_id_A=C.Row_id_B then C.field 
    when [Row_id_price_A]=[Row_id_price_B] then D.field
    else N'One of many: '+C.field
    end 
from A

outer apply (select top 1 * from B
where 
A.id=B.id
and Row_A=Row_B
) as C

outer apply (select top 1 * from B
where 
A.id=B.id
and Row_A=Row_B
and [Row_id_price_A]=[Row_id_price_B]
) as D

更新。 我添加了樣本數據:

CREATE TABLE dbo.TableA(
   id    INTEGER NOT NULL 
  ,price INTEGER NOT NULL
);
INSERT INTO TableA(id,price) VALUES (1,50);
INSERT INTO TableA(id,price) VALUES (2,20);
INSERT INTO TableA(id,price) VALUES (2,30);
INSERT INTO TableA(id,price) VALUES (2,50);
INSERT INTO TableA(id,price) VALUES (4,15);
INSERT INTO TableA(id,price) VALUES (4,5);
INSERT INTO TableA(id,price) VALUES (5,100);
INSERT INTO TableA(id,price) VALUES (5,100);

CREATE TABLE dbo.TableB(
   id    INTEGER NOT NULL 
  ,price INTEGER NOT NULL
  ,field VARCHAR(2) NOT NULL
);
INSERT INTO TableB(id,price,field) VALUES (1,1,'A1');
INSERT INTO TableB(id,price,field) VALUES (2,30,'A2');
INSERT INTO TableB(id,price,field) VALUES (2,50,'A3');
INSERT INTO TableB(id,price,field) VALUES (2,20,'A4');
INSERT INTO TableB(id,price,field) VALUES (5,5,'A5');
INSERT INTO TableB(id,price,field) VALUES (5,100,'A6');
INSERT INTO TableB(id,price,field) VALUES (5,100,'A7');
INSERT INTO TableB(id,price,field) VALUES (6,1,'A8');

聽起來像使用兩個左連接可以正常工作:

select
 ...
 coalesce (B1.Field, B2.Field) as Field,
 ...

left join TableB B1 on B1.id = TableA.id and B1.price = TableA.price
left join TableB B2 on B2.id = TableA.id

這通常很棘手,因為它可能會導致行重復出現問題,但在您的情況下不應該受到影響。

如果您還需要One of many文本中的One of many ,只需將其添加到coalesce,例如coalesce(B1.Field, 'One of many: ' + B2.Field) - 確保您擁有正確的類型。

編輯:

哦,你關心重復。 在這種情況下,子查詢可能是更好的選擇:

select
 ...
 coalesce(B1.Field, (select top 1 Field from TableB where id = TableA.id)) as Field
 ...

您可以與Table2進行兩次left join (一次用於完全匹配,一次用於一對多匹配)並使用ROW_NUMBER()管理完全匹配的行關聯

像這樣的東西。 SQL小提琴

樣本數據

CREATE TABLE Table1
(
    ID INT NOT NULL,
    Price INT NOT NULL
);

CREATE TABLE Table2
(
    ID INT NOT NULL,
    Price INT NOT NULL,
    Field VARCHAR(20) NOT NULL
);

INSERT INTO Table1 VALUES(1,50),(2,20),(2,30),(2,50),(4,15),(4,5),(5,100),(5,100);
INSERT INTO Table2 VALUES
    (1,1,'A1'),(2,30,'A2'),(2,50,'A3'),(2,20,'A4'),
    (5,5,'A5'),(5,100,'A6'),(5,100,'A7'),(6,1,'A8');

詢問

;WITH CT1 AS
(
SELECT *,rn = ROW_NUMBER()OVER(PARTITION BY ID,Price ORDER BY Price)
FROM Table1
), CT2 AS
(
SELECT *,rn = ROW_NUMBER()OVER(PARTITION BY ID,Price ORDER BY Field),
cc = ROW_NUMBER()OVER(PARTITION BY ID ORDER BY Price ASC)
FROM Table2
)
SELECT T1.*,ISNULL(T2.Field,'One of Many: ' + T3.Field) as Field
FROM CT1 T1 
LEFT JOIN CT2 T2 
    ON T1.ID = T2.ID
    AND (T1.Price = T2.Price AND T1.rn = T2.rn)
LEFT JOIN CT2 T3
    ON T1.ID = T3.ID
        AND T3.cc = 1
    ORDER BY T1.Id,T1.Price

產量

| ID | Price | rn |           Field |
|----|-------|----|-----------------|
|  1 |    50 |  1 | One of Many: A1 |
|  2 |    20 |  1 |              A4 |
|  2 |    30 |  1 |              A2 |
|  2 |    50 |  1 |              A3 |
|  4 |     5 |  1 |          (null) |
|  4 |    15 |  1 |          (null) |
|  5 |   100 |  1 |              A6 |
|  5 |   100 |  2 |              A7 |

只需使用此...

BEGIN TRAN
    SELECT A.id, A.price, B.field
    INTO #X
    FROM TableA A
    LEFT JOIN TableB B ON A.id = B.id AND A.price = B.price
    GROUP BY A.id, A.price, B.field

    SELECT X.id, X.price, IIF(X.price = B.price, B.field, 'One Of Many ' + B.field)
    FROM #X X
    LEFT JOIN TableB B ON X.id= B.id
    WHERE X.price = IIF(X.field IS NULL, X.price, B.price)
    GROUP BY X.id, X.price, B.price, B.field
ROLLBACK

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM