如何匹配'并且'无与伦比的'单个表中的行

时间:2018-04-17 16:21:07

标签: sql-server stored-procedures

我希望有两个存储过程可以匹配'并且'无与伦比的'行,分别......来自单个表......

'匹配'行是两行,状态分别为1和2,相同:

uID aID cID and pID

无与伦比的' row是一个状态为1的行,但是没有另一个状态为2的行具有相同的uID,aID,cID和pID

(为简洁起见,我已从数据中删除了唯一标识符Indx)

示例数据

uID aID cID pID state   occurs
10  200 5000    1240    1   2018-04-17 08:12:13.367
80  542 9000    5700    1   2018-04-17 08:12:54.113
10  240 5000    3860    1   2018-04-17 08:13:09.817
10  200 5000    1240    2   2018-04-17 08:13:18.010
30  240 7000    5938    1   2018-04-17 08:13:31.510
80  542 9000    5700    2   2018-04-17 08:14:04.363

以下是匹配'的示例行

uID aID cID pID state   occurs
10  200 5000    1240    1   2018-04-17 08:12:13.367
10  200 5000    1240    2   2018-04-17 08:13:18.010
80  542 9000    5700    1   2018-04-17 08:12:54.113
80  542 9000    5700    2   2018-04-17 08:14:04.363

以下是“无与伦比”的例子。行

uID aID cID pID state   occurs
10  240 5000    3860    1   2018-04-17 08:13:09.817
30  240 7000    5938    1   2018-04-17 08:13:31.510

匹配行代码

我遇到困难的地方围绕着对匹配集合进行分组的声明...我想我可以做这样的事情来获得两行1和2但没有这样的运气....

select uID, aID, cID, pID, state
from Data where state in (1,2) 
group by uID, aID, cID, pID, state
having state = 2 and state = 1

不匹配的行代码

然后我想我可以为不匹配的行做类似的事情,但这也不起作用......

select uID, aID, cID, pID, state
from Data where state in (1,2) 
group by uID, aID, cID, pID, state
having state != 2 and state = 1

我需要一些帮助 ...谢谢

基础设施

以下是创建表格的代码:

CREATE TABLE [dbo].[Data](
    [INDX] [uniqueidentifier] NOT NULL,
    [uID] [int] NOT NULL,
    [aID] [int] NOT NULL,
    [cID] [int] NOT NULL,
    [pID] [int] NOT NULL,
    [state] [int] NOT NULL,
    [occurs] [datetime] NOT NULL,
 CONSTRAINT [PK_Data] PRIMARY KEY CLUSTERED 
(
    [INDX] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

存储过程到"插入数据"

CREATE PROCEDURE [dbo].[InsertData]
    -- Add the parameters for the stored procedure here

    @userID int, 
    @appID int, 
    @compID int, 
    @procID int, 
    @state int,
    @occurence datetime

AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here

        declare @indx as uniqueidentifier
        set @indx = NEWID();

        insert into [Data]
        Values(
                @indx,
                @userID,
                @appID,
                @compID,
                @procID,
                @state,
                @occurence
                )

END
GO

这里有一些代码可以帮助填充表格:

declare @userID int
declare @appID int
declare @compID int
declare @procID int
declare @state int
declare @occurence datetime

set @userID = 10
set @appID = 200
set @compID = 5000
set @procID = 1240
set @state = 1

set @occurence = GETDATE();
EXEC InsertData @userID, @appID, @compID, @procID, @state, @occurence

添加其他状态时进行测试:

    set @userID = 80
    set @appID = 546
    set @compID = 9000
    set @procID = 5700
    set @state = 3
    set @occurence = GETDATE();
    EXEC InsertData @userID, @appID, @compID, @procID, @state, @occurence

所以我结束了这个数据集:

uID aID cID pID state
10  200 5000    1240    2
10  200 5000    1240    1
10  240 5000    3860    1
80  542 9000    5700    1
30  240 7000    5938    1
80  546 9000    5700    3
80  542 9000    5700    2

所以... scsimon ...你的查询效果很好......但如果是这样的话会怎么样:

添加了新的重复数据

uID aID cID pID state
10  200 5000    1240    1
80  542 9000    5700    1
10  240 5000    3860    1
10  200 5000    1240    2
30  240 7000    5938    1
80  542 9000    5700    2
80  546 9000    4502    3
10  200 5000    1240    1
10  200 5000    1240    2

查询结果,即结束......

uID aID cID pID state   occurs
10  200 5000    1240    1   2018-04-17 11:57:22.693
10  200 5000    1240    1   2018-04-17 11:57:29.797
10  200 5000    1240    2   2018-04-17 11:57:25.740
10  200 5000    1240    2   2018-04-17 11:57:30.827
80  542 9000    5700    1   2018-04-17 11:57:23.710
80  542 9000    5700    2   2018-04-17 11:57:27.767

但我真正想要的是:

uID aID cID pID state   occurs
10  200 5000    1240    1   2018-04-17 11:57:22.693
10  200 5000    1240    2   2018-04-17 11:57:25.740

10  200 5000    1240    1   2018-04-17 11:57:29.797
10  200 5000    1240    2   2018-04-17 11:57:30.827

80  542 9000    5700    1   2018-04-17 11:57:23.710
80  542 9000    5700    2   2018-04-17 11:57:27.767

最终答案(谢谢scsimon)

'匹配'

select t.uID, t.aID, t.cID, t.pID, t.state, t.occurs
from Data t
inner join
    (select uID, aID, cID, pID
     from Data
     where state in (1,2) --optional if needed
     group by uID, aID, cID, pID
     having count(*) > 1) t2 on 
 t2.uID = t.uID
 and t2.aID = t.aID
 and t2.cID = t.cID
 and t2.pID = t.pID
 order by uID, occurs, state

返回一组:

uID aID cID pID state   occurs
10  200 5000    1240    1   2018-04-17 11:57:22.693
10  200 5000    1240    2   2018-04-17 11:57:25.740
10  200 5000    1240    1   2018-04-17 11:57:29.797
10  200 5000    1240    2   2018-04-17 11:57:30.827
80  542 9000    5700    1   2018-04-17 11:57:23.710
80  542 9000    5700    2   2018-04-17 11:57:27.767

'不匹配'

select t.uID, t.aID, t.cID, t.pID, t.state, t.occurs
from Data t
inner join
    (select uID, aID, cID, pID
     from Data
     where state in (1,2) --optional if needed
     group by uID, aID, cID, pID
     having count(*) = 1) t2 on 
 t2.uID = t.uID
 and t2.aID = t.aID
 and t2.cID = t.cID
 and t2.pID = t.pID
 order by occurs

返回一个集合:

uID aID cID pID state   occurs
10  240 5000    3860    1   2018-04-17 11:57:24.727
30  240 7000    5938    1   2018-04-17 11:57:26.753

3 个答案:

答案 0 :(得分:2)

假设uID, aID, cID, pID的每个唯一耦合只会在这些状态中一次,您可以使用它。

--matching rows
select t.*
from table t
inner join
    (select uID, aID, ,cID, pID
     from table
     where state in (1,2) --optional if needed
     group by uID, aID, cID, pID
     having count(*) > 1) t2 on 
 t2.uID = t.uID
 and t2.aID = t.aID
 and t2.cID = t.cID
 and t2.pID = t.pID


 --unmatching rows
select t.*
from table t
inner join
    (select uID, aID, ,cID, pID
     from table
     where state in (1,2) --optional if needed
     group by uID, aID, cID, pID
     having count(*) = 1) t2 on 
 t2.uID = t.uID
 and t2.aID = t.aID
 and t2.cID = t.cID
 and t2.pID = t.pID

答案 1 :(得分:1)

我能够使用existsnot exists

复制您的预期输出
--Matched row code
SELECT * 
  FROM Data D1
 WHERE EXISTS (SELECT *
                 FROM Data D2
                WHERE D2.uID = D1.uID AND D2.aID = D1.aID AND D2.cID = D1.cID
                  AND D2.state = 2)
ORDER BY uID, state

--Unmatched row code    
SELECT * 
  FROM Data D1
 WHERE NOT EXISTS (SELECT *
                     FROM Data D2
                    WHERE D2.uID = D1.uID AND D2.aID = D1.aID AND D2.cID = D1.cID
                      AND D2.state = 2)
ORDER BY uID, state

答案 2 :(得分:1)

这个怎么样?我假设这里只有2个状态1和2。

SELECT  a.*
FROM    Data a
  JOIN (SELECT uID, aID, cID, pID, Count(*) as NumMatches
        FROM   Data
        Group By uID, aID, cID, pID
        Having Count(*) = 2) b ON a.uID = b.uID and a.aID = b.aID and a.cID = b.cID and a.pID = b.pID
Order by a.uID, a.aID, a.cID, a.pID 

和非匹配

SELECT  a.*
FROM    Data a
  LEFT OUTER JOIN (SELECT uID, aID, cID, pID, Count(*) as NumMatches
        FROM   Data
        Group By uID, aID, cID, pID
        Having Count(*) = 2) b ON a.uID = b.uID and a.aID = b.aID and a.cID = b.cID and a.pID = b.pID
WHERE IsNull(b.uID,0) = 0
Order by a.uID, a.aID, a.cID, a.pID