如何在每个类别中仅使用一对一行进行左连接。这是类别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');
答案 0 :(得分:1)
使用两个左连接听起来很不错:
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
文字,只需将其添加到合并,例如coalesce(B1.Field, 'One of many: ' + B2.Field)
- 确保你有合适的类型。
修改强>
哦,你确实关心重复。在这种情况下,子查询可能是更好的选择:
select
...
coalesce(B1.Field, (select top 1 Field from TableB where id = TableA.id)) as Field
...
答案 1 :(得分:1)
您可以将两个left join
与Table2(一个用于完全匹配,一个用于一对多匹配)并使用ROW_NUMBER()
管理完全匹配的行关联
像这样的东西。 SQL Fiddle
示例数据
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 |
答案 2 :(得分:0)
只需使用此...
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