2014-10-30 84 views
1

鉴于以下数据SQL查询递归找到关系记录基于2场

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 = 1Email = "blah1"

我需要写一个SQL查询,让我所有的独特记录其递归地包含关于用户ID或电子邮件匹配

实施例结果

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 = 1Email = "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 = 4Email = "blah3"随后通将产生

OrderId UserId Email PostCode Country 
7  4  blah3 111   au 
8  4  blah5 111   au 

等为在一组的所有相关的记录以产生实施例以上结果

所示这是可能做CTEs可能?

回答

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 
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' 
     ) 

UPDATE的问题是改变,这里是新的答案:

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) 
+0

确定这解决方案适用于给出的数据,但如果有电子邮件和IDS之间的关系更加它不会去接他们不幸的是,我已经更新的问题表现出更多的相关记录 – 2014-10-30 23:41:26

+0

@Saruman那是相当的一个与你最初发布的问题不同的问题,甚至标题中明确地提到了2。我在第一个下面放了一个新的代码块。 – Tristan 2014-11-01 09:10:40

+0

感谢您的更新答案,今天就对它进行测试 – 2014-11-02 21:19:54