2014-10-30 93 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