我的情况是这样的。我有一个带有pk“Parent”的产品表,其中包含“Components”数据看起来像这样
Parent(PK) Component
Car1 Wheel
Car1 Tyre
Car1 Roof
Car2 Alloy
Car2 Tyre
Car2 Roof
Car3 Alloy
Car3 Tyre
Car3 Roof
Car3 Leather Seats
现在我要做的是一些查询,我可以提供两个代码并查看差异... IE如果我输入“Car1”,“Car2”它将返回类似的东西;
Parent Component
Car1 Wheel
Car2 Alloy
因为这是两者之间的差异。如果我说“Car1”,“Car3”我会期待;
Parent Component
Car1 Wheel
Car3 Alloy
Car3 Leather Seats
非常感谢您对此事的帮助。
答案 0 :(得分:4)
没有GROUP BY或UNION:
create table Products (
Parent varchar(20) not null,
Component varchar(20) not null
)
insert into Products (Parent,Component)
select 'Car1','Wheel' union all
select 'Car1','Tyre' union all
select 'Car1','Roof' union all
select 'Car2','Alloy' union all
select 'Car2','Tyre' union all
select 'Car2','Roof' union all
select 'Car3','Alloy' union all
select 'Car3','Tyre' union all
select 'Car3','Roof' union all
select 'Car3','Leather Seats'
go
select
ISNULL (a.Parent,b.Parent) as Parent,
ISNULL (a.Component,b.Component) as Component
from
Products a
full outer join
Products b
on
a.Component = b.Component and
a.Parent = 'Car1' and
b.Parent = 'Car3'
where
(a.Parent = 'Car1' and b.Parent is null) or
(b.Parent = 'Car3' and a.Parent is null)
答案 1 :(得分:3)
DECLARE @ThisCar .., @ThatCar;
SELECT @ThisCar = '...', @ThatCar = '...';
SELECT
Parent, Component
FROM
MyTable M1
WHERE
M1.Parent = @ThisCar
AND
NOT EXISTS (SELECT *
FROM
MyTable M2
WHERE
M2.Parent = @ThatCar AND M1.Component = M2.Component)
UNION
SELECT
Parent, Component
FROM
MyTable M2
WHERE
M2.Parent = @ThatCar
AND
NOT EXISTS (SELECT *
FROM
MyTable M1
WHERE
M1.Parent = @ThisCar AND M1.Component = M2.Component):
答案 2 :(得分:2)
我尝试了这个,它返回了预期的结果:
Select Min(parent) As parent, component
From
(
Select parent, component
From products
Where parent In ( 'Car1', 'Car3' )
)
Group By component
Having Count(*) = 1
子查询获取Car1
和Car2
的所有组件,并使用Group By
和Having
- 子句删除两辆车都具有的组件。
答案 3 :(得分:1)
替代
DECLARE @thisCar varchar(20)
DECLARE @thatCar varchar(20)
SET @thisCar = 'Car1'
SET @thatCar = 'Car2'
SELECT * FROM
(
SELECT @thisCar AS Parent, Component FROM products WHERE parent = @thisCar
EXCEPT
SELECT @thisCar AS Parent, Component FROM products WHERE parent = @thatCar
) c1
UNION ALL
SELECT * FROM
(
SELECT @thatCar AS Parent, Component FROM products WHERE parent = @thatCar
EXCEPT
SELECT @thatCar AS Parent, Component FROM products WHERE parent = @thisCar
) c2
答案 4 :(得分:0)
我描述了,到目前为止最快的解决方案是:
select
ISNULL (a.Parent,b.Parent) as Parent,
ISNULL (a.Component,b.Component) as Component
from
(select * from Products where Parent = 'Car1') as a
full outer join
(select * from Products where Parent = 'Car2') as b
on
a.Component = b.Component
where
(a.Parent = 'Car1' and b.Parent is null) or
(b.Parent = 'Car2' and a.Parent is null)
它比@gbns解决方案快30%左右,比@Damiens解决方案快很多倍
勇敢的是,这里有一些执行计划:
select ISNULL (a.Parent,b.Parent) as Parent, ISNULL (a.Component,b.Component) as Component from (select * from Products where Parent = 'Car1') as a full outer join (select * from Products where Parent = 'Car2') as b StmtText ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--Compute Scalar(DEFINE:([Expr1012]=isnull([Expr1004],[Expr1010]), [Expr1013]=isnull([Expr1005],[Expr1011]))) |--Filter(WHERE:([Expr1004]='Car1' AND [Expr1010] IS NULL OR [Expr1010]='Car2' AND [Expr1004] IS NULL)) |--Hash Match(Full Outer Join, HASH:([CloudDb].[dbo].[Products].[Component])=([CloudDb].[dbo].[Products].[Component]), RESIDUAL:([CloudDb].[dbo].[Products].[Component]=[CloudDb].[dbo].[Products].[Component])) |--Compute Scalar(DEFINE:([Expr1004]=[CloudDb].[dbo].[Products].[Parent], [Expr1005]=[CloudDb].[dbo].[Products].[Component])) | |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000])) | |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts]), SEEK:([CloudDb].[dbo].[Products].[Parent]='Car1') ORDERED FORWARD) | |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD) |--Compute Scalar(DEFINE:([Expr1010]=[CloudDb].[dbo].[Products].[Parent], [Expr1011]=[CloudDb].[dbo].[Products].[Component])) |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1006])) |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts]), SEEK:([CloudDb].[dbo].[Products].[Parent]='Car2') ORDERED FORWARD) |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products]), SEEK:([Bmk1006]=[Bmk1006]) LOOKUP ORDERED FORWARD) StmtText ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SELECT Parent, Component FROM Products M1 WHERE M1.Parent = 'Car1' AND NOT EXISTS (SELECT * FROM Products M2 WHERE M2.Parent = 'Car2' AND M1.Component = M2.Component) UNION ALL SELEC StmtText ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--Concatenation |--Nested Loops(Left Anti Semi Join, OUTER REFERENCES:([M1].[Component])) | |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000])) | | |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts] AS [M1]), SEEK:([M1].[Parent]='Car1') ORDERED FORWARD) | | |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products] AS [M1]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD) | |--Top(TOP EXPRESSION:((1))) | |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1003])) | |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts] AS [M2]), SEEK:([M2].[Parent]='Car2') ORDERED FORWARD) | |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products] AS [M2]), SEEK:([Bmk1003]=[Bmk1003]), WHERE:([CloudDb].[dbo].[Products].[Component] as [M1].[Component]=[CloudDb].[dbo].[Products].[Component] as [M2].[Component]) LOOKUP ORDERED FORWA |--Nested Loops(Left Anti Semi Join, OUTER REFERENCES:([M2].[Component])) |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1007])) | |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts] AS [M2]), SEEK:([M2].[Parent]='Car2') ORDERED FORWARD) | |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products] AS [M2]), SEEK:([Bmk1007]=[Bmk1007]) LOOKUP ORDERED FORWARD) |--Top(TOP EXPRESSION:((1))) |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1010])) |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts] AS [M1]), SEEK:([M1].[Parent]='Car1') ORDERED FORWARD) |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products] AS [M1]), SEEK:([Bmk1010]=[Bmk1010]), WHERE:([CloudDb].[dbo].[Products].[Component] as [M1].[Component]=[CloudDb].[dbo].[Products].[Component] as [M2].[Component]) LOOKUP ORDERED FORWA StmtText ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- SELECT * FROM ( SELECT 'Car1' AS Parent, Component FROM products WHERE parent = 'Car1' EXCEPT SELECT 'Car1'AS Parent, Component FROM products WHERE parent = 'Car2' ) c1 UNION ALL SELECT * FROM ( SELECT 'Car2' AS Parent, Component StmtText -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |--Concatenation |--Nested Loops(Left Anti Semi Join, OUTER REFERENCES:([CloudDb].[dbo].[Products].[Component])) | |--Sort(DISTINCT ORDER BY:([CloudDb].[dbo].[Products].[Component] ASC)) | | |--Compute Scalar(DEFINE:([Expr1004]='Car1')) | | |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1000])) | | |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts]), SEEK:([CloudDb].[dbo].[Products].[Parent]='Car1') ORDERED FORWARD) | | |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products]), SEEK:([Bmk1000]=[Bmk1000]) LOOKUP ORDERED FORWARD) | |--Top(TOP EXPRESSION:((1))) | |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1005])) | |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts]), SEEK:([CloudDb].[dbo].[Products].[Parent]='Car2') ORDERED FORWARD) | |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products]), SEEK:([Bmk1005]=[Bmk1005]), WHERE:([CloudDb].[dbo].[Products].[Component]=[CloudDb].[dbo].[Products].[Component]) LOOKUP ORDERED FORWARD) |--Nested Loops(Left Anti Semi Join, OUTER REFERENCES:([CloudDb].[dbo].[Products].[Component])) |--Sort(DISTINCT ORDER BY:([CloudDb].[dbo].[Products].[Component] ASC)) | |--Compute Scalar(DEFINE:([Expr1014]='Car2')) | |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1010])) | |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts]), SEEK:([CloudDb].[dbo].[Products].[Parent]='Car1') ORDERED FORWARD) | |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products]), SEEK:([Bmk1010]=[Bmk1010]) LOOKUP ORDERED FORWARD) |--Top(TOP EXPRESSION:((1))) |--Nested Loops(Inner Join, OUTER REFERENCES:([Bmk1015])) |--Index Seek(OBJECT:([CloudDb].[dbo].[Products].[idxProducts]), SEEK:([CloudDb].[dbo].[Products].[Parent]='Car2') ORDERED FORWARD) |--RID Lookup(OBJECT:([CloudDb].[dbo].[Products]), SEEK:([Bmk1015]=[Bmk1015]), WHERE:([CloudDb].[dbo].[Products].[Component]=[CloudDb].[dbo].[Products].[Component]) LOOKUP ORDERED FORWARD)
稍微冗长的查询有时可以导致更简单的执行计划。