在SQL Server中获取相互匹配
我想把买家和卖家配对。我这样做是为了让它尽可能简单 我有一张桌子:tmpSales。在其中,我有一个TransID、BuyerID、SellerID、Item和Date 有时买方也是卖方,反之亦然 我想要的是一张记录,一个买主卖给一个卖主,同一个卖主卖给同一个买主 我有一个查询,它可以正常工作:在SQL Server中获取相互匹配,sql,sql-server,Sql,Sql Server,我想把买家和卖家配对。我这样做是为了让它尽可能简单 我有一张桌子:tmpSales。在其中,我有一个TransID、BuyerID、SellerID、Item和Date 有时买方也是卖方,反之亦然 我想要的是一张记录,一个买主卖给一个卖主,同一个卖主卖给同一个买主 我有一个查询,它可以正常工作: SELECT * FROM [dbo].[tmpSales] T1 INNER JOIN [dbo].[tmpSales] T2 ON T1.[BuyerID] = T2.[SellerID] AND
SELECT *
FROM [dbo].[tmpSales] T1
INNER JOIN [dbo].[tmpSales] T2
ON T1.[BuyerID] = T2.[SellerID]
AND T2.[BuyerID] = T1.[SellerID]
但是,它为每个匹配返回2条记录。有没有办法在BuyerID和SellerID都存在的情况下返回一条记录
示例数据如下所示:
TransID BuyerID SellerID ItemID Date
1 10012 10032 65 10/15/2014
2 11111 10012 120 12/15/2014
3 10032 10012 32 2/2/2015
4 11111 10032 30 2/10/2015
5 10012 11111 45 3/1/2015
在本例中,我可以看到10012和10032都相互出售和购买,就像10012和11111一样。我只想要这样的东西:
ID1 ID2
10012 10032
10012 11111
数据将不断增长,因此它必须是动态的,也就是说,我不能在代码中添加类似的内容,其中BuyerID='10012'
编辑:实际上,我想做的是将其作为一个视图或存储过程,并向其传递两个ID,让它告诉我是否存在相互匹配。通过选择第一个,您可以轻松地将select中的数据限制为一种方式,如下所示:
SELECT *
FROM [dbo].[tmpSales] T1
INNER JOIN [dbo].[tmpSales] T2
ON T1.[BuyerID] = T2.[SellerID]
AND T2.[BuyerID] = T1.[SellerID]
AND T2.[BuyerID] > T1.[BuyerID]
因此,这样一来,拥有更大买家ID的买家始终是第二个买家,并且您也可以在一个过程中使用类似的逻辑。您可以使用以下查询来检索所有相互映射
SELECT DISTINCT T.BuyerID AS ID1,T.SellerID AS ID2
FROM [dbo].[tmpSales] T
WHERE EXISTS (SELECT *
FROM [dbo].[tmpSales] T1
WHERE T1.BuyerID = T.SellerId
AND T1.SellerID = T.BuyerID)
如果只想检查指定的对,也可以这样做
DECLARE @Id1 INT
DECLARE @Id2 INT
SELECT *
FROM [dbo].[tmpSales] T
WHERE T.BuyerID = @Id1
AND T.SellerID = @Id2
AND EXISTS (SELECT *
FROM [dbo].[tmpSales] T1
WHERE T1.BuyerID = @Id2
AND T1.SellerID = @Id1)
这在MySql中是存在的,但同样的原则也适用 此查询获取两个人之间进行的交易的所有不同用户,其中他们都是不同交易中的买方和卖方。由于这包括所有交易,每个参与者将被列为两次,一次作为买方,一次作为卖方,如果两个方向都有一次以上的销售,则会被列为更多次,而不带明显标记
select
distinct sale1.buyer_id party1, sale1.seller_id party2
from
temp_sale sale1
join temp_sale sale2 on sale1.buyer_id = sale2.seller_id and sale1.seller_id = sale2.buyer_id
;
这将提供以下行:
+ ----------- + ----------- +
| party1 | party2 |
+ ----------- + ----------- +
| 10032 | 10012 |
| 10012 | 11111 |
| 10012 | 10032 |
| 11111 | 10012 |
+ ----------- + ----------- +
4 rows
+ ----------- + ----------- +
| party1 | party2 |
+ ----------- + ----------- +
| 10032 | 10012 |
| 11111 | 10012 |
+ ----------- + ----------- +
2 rows
添加下面的where子句将使您获得一组不同的个体,这些个体既相互购买又相互出售
select
distinct sale1.buyer_id party1, sale1.seller_id party2
from
temp_sale sale1
join temp_sale sale2 on sale1.buyer_id = sale2.seller_id and sale1.seller_id = sale2.buyer_id
where
sale1.buyer_id > sale1.seller_id
;
这将提供以下行:
+ ----------- + ----------- +
| party1 | party2 |
+ ----------- + ----------- +
| 10032 | 10012 |
| 10012 | 11111 |
| 10012 | 10032 |
| 11111 | 10012 |
+ ----------- + ----------- +
4 rows
+ ----------- + ----------- +
| party1 | party2 |
+ ----------- + ----------- +
| 10032 | 10012 |
| 11111 | 10012 |
+ ----------- + ----------- +
2 rows
为完整起见,以下是整个示例:
use example;
drop table if exists temp_sale;
create table temp_sale (
id int,
buyer_id int,
seller_id int,
item_id int,
date date
);
insert into temp_sale values (1, 10012, 10032, 65, '2014-10-15');
insert into temp_sale values (2, 11111, 10012, 120, '2014-12-15');
insert into temp_sale values (3, 10032, 10012, 32, '2015-02-02');
insert into temp_sale values (4, 11111, 10032, 30, '2015-02-10');
insert into temp_sale values (5, 10012, 11111, 45, '2015-03-01');
select
distinct sale1.buyer_id party1, sale1.seller_id party2
from
temp_sale sale1
join temp_sale sale2 on sale1.buyer_id = sale2.seller_id and sale1.seller_id = sale2.buyer_id
;
select
distinct sale1.buyer_id party1, sale1.seller_id party2
from
temp_sale sale1
join temp_sale sale2 on sale1.buyer_id = sale2.seller_id and sale1.seller_id = sale2.buyer_id
where
sale1.buyer_id > sale1.seller_id
;
啊。。。这是一个非常有趣的问题,有三个人比我先到这里。在任何情况下,我建议在数据集增长时将这些数据记录到表中,而不是在每次需要查看时都运行一个特别的查询,但是对于初始数据填充,这里是我收集的一个小光标。希望有帮助
if object_id(N'tempdb..#FindMe') is not null
drop table #FindMe ;
if object_id(N'tempdb..#UniqueRelationships') is not null
drop table #UniqueRelationships ;
create table #UniqueRelationships
( Id1 int,
Id2 int );
declare @Table table
([TransID] int not null
,[BuyerID] int not null
,[SellerID] int not null
,[ItemID] int not null
,[Date] date not null );
insert @table values
(1,10012,10032,65,'2014-10-15 00:00:00.0'),
(2,11111,10012,120,'2014-12-15 00:00:00.0'),
(3,10032,10012,32,'2015-02-02 00:00:00.0'),
(4,11111,10032,30,'2015-02-10 00:00:00.0'),
(5,10012,11111,45,'2015-03-01 00:00:00.0');
select
t1.BuyerID
,t1.SellerID
into #FindMe
from @table t1
join @Table t2 on t1.BuyerID = t2.SellerID
and t2.BuyerID = t1.SellerID ;
declare
@IdA int,
@IdB int;
declare FindMe cursor for
select BuyerId, SellerId from #FindMe ;
open FindMe ;
fetch next from FindMe into @IdA, @IdB ;
while @@fetch_status = 0
begin
if not exists( select 1
from #UniqueRelationships
where ( Id1 = @IdA
and Id2 = @IdB )
or ( Id2 = @IdA
and Id1 = @IdB ) )
begin
insert #UniqueRelationships
( Id1, Id2 )
select
@IdA
,@IdB
end
fetch next from FindMe into @IdA, @IdB ;
end ;
close FindMe ;
deallocate FindMe ;
select * from #UniqueRelationships ;
if object_id(N'tempdb..#FindMe') is not null
drop table #FindMe ;
if object_id(N'tempdb..#UniqueRelationships') is not null
drop table #UniqueRelationships ;
它实际上非常简单,要么使用CTE/派生表解决方案,要么使用WHERE EXISTS解决方案。再加上@TabAlleman所说的,以避免每次匹配获得两条记录,即买方1与卖方2,买方2与卖方1,只需使用WHERE子句断言BuyerId