鉴于以下数据
OrderId UserId Email PostCode Country
1 1 blah1 111 au
2 1 blah2 111 au
3 1 blah3 111 au
4 2 blah3 111 au
5 3 blah4 111 nz
6 3 blah4 111 nz
7 4 blah3 111 au
8 4 blah5 111 au
此输入UserID = 1
,Email = "blah1"
我需要编写一个sql查询,它为我提供了所有唯一的记录,这些记录递归地包含UserId或Email上的匹配
示例结果
OrderId UserId Email PostCode Country
1 1 blah1 111 au
2 1 blah2 111 au
3 1 blah3 111 au
4 2 blah3 111 au
7 4 blah3 111 au
8 4 blah5 111 au
E.g
第一遍将根据UserID = 1
或 Email = "blah1"
生成以下内容
OrderId UserId Email PostCode Country
1 1 blah1 111 au
2 1 blah2 111 au
3 1 blah3 111 au
后续传递UserID = 1
或 Email = "blah3"
会产生
OrderId UserId Email PostCode Country
3 1 blah3 111 au
4 2 blah3 111 au
7 4 blah3 111 au
后续传递UserID = 4
或 Email = "blah3"
会产生
OrderId UserId Email PostCode Country
7 4 blah3 111 au
8 4 blah5 111 au
以及所有相关记录,以便生成上面显示的示例结果
这可能与CTE有关吗?
答案 0 :(得分:0)
您不需要CTE,请查看子查询:
declare @src table (
OrderId int
, UserId int
, Email nvarchar(50)
, PostCode int
, Country nvarchar(50)
)
insert @src
select * from (values
(1,1,'blah1',111,'au'),
(2,1,'blah2',111,'au'),
(3,1,'blah3',111,'au'),
(4,2,'blah3',111,'au'),
(5,3,'blah3',111,'nz'),
(6,3,'blah3',111,'nz')) src(OrderId, UserId, Email, PostCode, Country)
select distinct *
from @src
where Email in (
select Email
from @src
where UserId = 1
) or
UserId in (
select UserId
from @src
where Email = 'blah1'
)
更新问题已更改,以下是新答案:
use guidion_test
go
if OBJECT_ID('demo_src') is not null drop table demo_src
create table demo_src (
OrderId int
, UserId int
, Email nvarchar(50)
, PostCode int
, Country nvarchar(50)
)
insert demo_src
select * from (values
(1,1,'blah1',111,'au'),
(2,1,'blah2',111,'au'),
(3,1,'blah3',111,'au'),
(4,2,'blah3',111,'au'),
(5,3,'blah3',111,'nz'),
(6,3,'blah3',111,'nz')) src(OrderId, UserId, Email, PostCode, Country);
declare @search_user int = 1;
with cte
as (
select OrderId
, UserId
, Email
, PostCode
, Country
from demo_src
where UserId = @search_user
union all
select s.OrderId
, s.UserId
, s.Email
, s.PostCode
, s.Country
from demo_src s
join cte c
on s.UserId = c.UserId
or s.OrderId = c.OrderId
or s.Email = c.Email
or s.PostCode = c.PostCode
or s.Country = c.Country
)
select top 10 *
from cte
option (maxrecursion 100)
答案 1 :(得分:0)
经过大量的反复试验后,我认为我找到了最合适的解决方案
如果有人能想出更好的方法来达到相同的效果或优化我所做的事情,那就标记你的答案是正确的
USE [test]
GO
/****** Object: StoredProcedure [dbo].[uspGetSimilar] Script Date: 10/11/2014 12:49:03 PM ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[uspGetSimilar]
@UserId varchar(20),
@Email varchar(50)
AS
BEGIN
SET NOCOUNT ON;
-- set test src tables
declare @src table (Id int,UserId nvarchar(20), Email nvarchar(50), PostCode int, Country nvarchar(50))
-- inset test data
insert @src
select * from (values
(1,'1','blah1',111,'au'),
(2,'1','blah2',111,'au'),
(3,'1','blah3',111,'au'),
(4,'2','blah4',111,'au'),
(5,'2','blah3',111,'nz'),
(6,'4','blah4',111,'nz'),
(7,'5','blah4',111,'nz'),
(8,'5','blah6',111,'nz'),
(9,'7','blah7',111,'nz'),
(10,'8','blah8',111,'nz'),
(11,'9','blah9',111,'nz'),
(12,'10','blah10',111,'nz'),
(13,'1','blah11',111,'nz')
) src(Id, UserId, Email, PostCode, Country)
select * from @src
-- declare table variables
declare @Ids table (Id int)
declare @Emails table (Email varchar(50), Searched bit)
declare @UserIds table (UserId varchar(20), Searched bit)
declare @Results table (Id int,UserId varchar(20),Email varchar(50),PostCode int, Country nvarchar(50))
-- Merge Initial UserId into UserIds table
if(@UserId is not null)
begin
merge into @UserIds u
using (
select @UserId as UserId
) t on t.UserId = u.UserId
when not matched then
insert (UserId,Searched) values (t.UserId,0);
end
-- Merge Initial Email into Emails table
if(@Email is not null)
begin
merge into @Emails u
using (
select @Email as Email
) t on t.Email = u.Email
when not matched then
insert (Email,Searched) values (t.Email,0);
end
-- while both variables have something in them, there are potentially more matches
while (@UserId is not null or @Email is not null)
begin
-- clear results
DELETE FROM @Results
-- Main search query
INSERT INTO @Results
SELECT Id, UserId, Email,PostCode,Country
FROM @src
Where (@UserId is not null and userId = @UserId) or (@Email is not null and Email = @Email)
-- if results are found merge
if (@@ROWCOUNT > 0)
begin
-- merge new ids
merge into @Ids i
using (
select Id from @Results
) t on t.Id = i.Id
when not matched then
insert (Id) values (t.Id);
-- merge new userIds
merge into @UserIds u
using (
select UserId from @Results
) t on t.UserId = u.UserId
when not matched then
insert (UserId,Searched) values (t.UserId,0);
-- merge new emails
merge into @Emails u
using (
select Email from @Results
) t on t.Email = u.Email
when not matched then
insert (Email,Searched) values (t.Email,0);
end
-- mark variables as searched in thier respective tables
UPDATE @UserIds set Searched = 1 where UserId = @UserId
UPDATE @Emails set Searched = 1 where Email = @Email
-- clear variables
set @UserId = null;
set @Email = null;
-- reset variables to the next unserached value
select top 1 @UserId = UserId from @UserIds where Searched = 0;
select top 1 @Email = Email from @Emails where Searched = 0;
end
select * from @Ids
END