按父或子ID获取所有重复数据[SQL Server]

时间:2016-06-22 16:38:40

标签: sql-server

我有名为EmailChangeRequest的表,其中包含以下列:

1. ChangeRequestId -- (INT) Primary Key + Auto Increment
2. UserId -- (INT)
3. VerificationCode -- (VARCHAR)
4. IsVerified -- (BIT)
5. OriginalRequestId -- (INT) -- Foreign Key with ChangeRequestId

这是EmailChangeRequest表格数据

ChangeRequestId  |  UserId  |  VerificationCode  | IsVerified | OriginalRequestId
    22           |   1      |    896524          |     0      |        NULL
    23           |   1      |    968521          |     0      |        22
    24           |   1      |    156874          |     0      |        22
    25           |   1      |    658932          |     0      |        22
    26           |   2      |    250489          |     0      |        NULL 

现在,我可以实现的目标:如果我通过ChangeRequestId = 22,那么他会向我提供ChangeRequestIdOriginalRequestId = 22的所有行。我可以通过以下查询轻松实现这一目标。

SELECT * FROM EmailChangeRequest
WHERE ChangeRequestId = 22 OR OriginalRequestId = 22

我想要的是什么:如果我将ChangeRequestId传递给232425,它也会给我相同的结果给出ChangeRequestId = 22

任何想法,我是如何做到这一点的?

5 个答案:

答案 0 :(得分:1)

这是你在找什么?

Drop Table #EmailChangeRequest
Create Table #EmailChangeRequest (ChangeRequestId Int,UserId Int,VerificationCode Int, IsVerified Int, OriginalRequestId Int)

Insert #EmailChangeRequest Values (22, 1,896524, 0,NULL)
Insert #EmailChangeRequest Values (23, 1,968521, 0,22)
Insert #EmailChangeRequest Values (24, 1,156874, 0,22)
Insert #EmailChangeRequest Values (25, 1,658932, 0,22)
Insert #EmailChangeRequest Values (26, 2,250489, 0,NULL )
Insert #EmailChangeRequest Values (22, 1,896524, 0,NULL)
Insert #EmailChangeRequest Values (23, 1,968521, 0,22)
Insert #EmailChangeRequest Values (24, 1,156874, 0,22)
Insert #EmailChangeRequest Values (25, 1,658932, 0,22)
Insert #EmailChangeRequest Values (26, 2,250489, 0,NULL )
Insert #EmailChangeRequest Values (27, 1,968521, 0,28)
Insert #EmailChangeRequest Values (28, 1,156874, 0,NULL)
Insert #EmailChangeRequest Values (29, 1,658932, 0,28)  


Select * From #EmailChangeRequest

Declare @ID Int = 22
;With cteReferenced As
(
Select OriginalRequestId 
    From #EmailChangeRequest 
    Where ChangeRequestId = @ID Or OriginalRequestId = @ID
)
SELECT * 
    FROM #EmailChangeRequest
    WHERE ChangeRequestId = @ID
Union -- removes duplicates between two queries ie @ID = 22 as opposed to Union All
SELECT * 
    FROM #EmailChangeRequest
    WHERE OriginalRequestId In (Select OriginalRequestId From cteReferenced) 
        Or ChangeRequestId In (Select OriginalRequestId From cteReferenced)

答案 1 :(得分:1)

使用递归CTE - 这是使用您的表和数据的示例: - 检查临时表是否存在并在必要时删除

if object_id('tempdb..#ecr') is not null
    drop table #ecr;

create table #ecr ( changerequestid   int not null
,                   userid            int not null
,                   verficationcode   varchar(10) not null
,                   isverified        bit
,                   originalrequestid int null );

insert #ecr
values ( 22, 1, 896524, 0, null )
,      ( 23, 1, 968521, 0, 22   )
,      ( 24, 1, 156874, 0, 22   )
,      ( 25, 1, 658932, 0, 22   )
,      ( 26, 1, 250489, 0, null );

declare @req_id int = 23; -- your example

with req -- recursive CTE - anchor is the row with the request id you submitted.
                         -- recursive member is the row with the first row's originalrequestid as it's own changerequestid
as
(
    select *
    from #ecr as a
    where changerequestid = @req_id
    union all
    select a.*
    from       #ecr as a
    inner join req  as r on (a.changerequestid = r.originalrequestid)
)
-- the above will give us the change request # 23 and all of its parent rows 
-- from the originalchangerequest column, until there are no more parent rows 
-- (until originalchangerequestid is null)

-- we use the recursive CTE, and then do ANOTHER union, select all rows which 
-- have any of the originalrequestid equal to any of the changerequestid from our CTE
-- this will give us the request we asked for, it's parent row, and all other rows with 
-- any of those rows as their parents.

select r.*
from req r
union
select a.*
from       #ecr a
inner join req  r on a.originalrequestid = r.changerequestid

答案 2 :(得分:0)

例如23:

SELECT * FROM EmailChangeRequest
WHERE (ChangeRequestId = 22 OR OriginalRequestId = 22) OR (ChangeRequestId = 23 OR OriginalRequestId = 23)

Brackets能够胜任工作。

答案 3 :(得分:0)

您可以使用以下脚本:

DECLARE @desiredID INT = 0
SELECT @desiredID = OriginalRequestId  
FROM EmailChangeRequest
WHERE ChangeRequestId = 23 -- Whatever value you pass

IF @desiredID = 0
BEGIN 
   SELECT * FROM EmailChangeRequest
   WHERE ChangeRequestId = @desiredID OR OriginalRequestId = @desiredID
END
ELSE
BEGIN
   SELECT * FROM EmailChangeRequest
   WHERE ChangeRequestId = 23 OR OriginalRequestId = 23 --This is for all other cases
END

答案 4 :(得分:0)

我查看此处发布的所有4个答案。其中两个不起作用,另外两个看起来很复杂。最后,我提出了以下解决方案:

DECLARE @ChangeRequestId INT = 23
DECLARE @OriginalRequestId INT;

SELECT @OriginalRequestId = ISNULL(OriginalRequestId, @ChangeRequestId)
FROM EmailChangeRequest
WHERE ChangeRequestId = @ChangeRequestId

SELECT * FROM EmailChangeRequest
WHERE ChangeRequestId = @OriginalRequestId
  OR OriginalRequestId = @OriginalRequestId