SQL - 查找唯一的最小值和关联列

时间:2011-06-21 15:46:45

标签: sql sql-server tsql

我有一组数据如下,显示了谁用记录做了什么的历史。每个记录的唯一标识符显示在“ID”中,“Rec No”是分配给与记录的每次交互的序号。

ID  Rec No  Who Type
1   1   Bob New
1   2   Bob Open
1   3   Bob Assign
1   4   Sarah   Add
1   5   Bob Add
1   6   Bob Close
2   1   John    New
2   2   John    Open
2   3   John    Assign
2   4   Bob Assign
2   5   Sarah   Add
2   6   Sarah   Close
3   1   Sarah   New
3   2   Sarah   Open
3   3   Sarah   Assign
3   4   Sarah   Close

我需要找到所有'分配'操作。但是,如果多个“分配”在某个ID中,我想找到第一个。然后我也想找到那个人的名字。

因此,从上述日期开始,我希望输出为 -

Who Count (assign)
Bob 1
John    1
Sarah   1

我目前的代码是 -

SELECT IH.WHO, Count(IH.ID)
FROM Table.INCIDENTS_H IH
WHERE (IH.TYPE = Assign)
GROUP BY IH.WHO

但这会将输出显示为 -

Who Count (assign)
Bob 2
John    1
Sarah   1

因为它发现Bob在ID 2,Rec No 4上做了一个分配。

任何帮助将不胜感激。我正在使用MS SQL。

6 个答案:

答案 0 :(得分:1)

我认为这样的事情就是你所追求的:

select 
  who, count(id) 
from (
  select ID, Who, row_number() over (partition by ID order by Rec) [rownum]
  from Table.INCIDENTS_H IH
  WHERE (IH.TYPE = Assign)
) a
where rownum = 1
group by who

这应该只计算每个ID组中的第一个Assign(按Rec排序)。

答案 1 :(得分:1)

您可以使用row_number来完成此操作

WITH INCIDENTS_H  as (
SELECT
1 as ID, 1 as RecNo, 'Bob' as Who, 'New' as type
UNION ALL SELECT 1,   2,   'Bob','Open'
UNION ALL SELECT 1,   3,   'Bob','Assign'
UNION ALL SELECT 1,   4,   'Sarah','Add'
UNION ALL SELECT 1,   5,   'Bob','Add'
UNION ALL SELECT 1,   6,   'Bob','Close'
UNION ALL SELECT 2,   1,   'John','New'
UNION ALL SELECT 2,   2,   'John','Open'
UNION ALL SELECT 2,   3,   'John','Assign'
UNION ALL SELECT 2,   4,   'Bob','Assign'
UNION ALL SELECT 2,   5,   'Sarah','Add'
UNION ALL SELECT 2,   6,   'Sarah','Close'
UNION ALL SELECT 3,   1,   'Sarah','New'
UNION ALL SELECT 3,   2,   'Sarah','Open'
UNION ALL SELECT 3,   3,   'Sarah','Assign'
UNION ALL SELECT 3,   4,   'Sarah','Close')
, GetTheMin AS (
SELECT 
    ROW_NUMBER() over (partition by id order by recno) row,
    ID,
    RecNo,
    Who,
    type

FROM 
    INCIDENTS_H
WHERE
    type = 'Assign'
)
SELECT Who,
COUNT(ID)
FROM GetTheMin
WHERE
    row = 1
GROUP BY 
    who

或者你可以使用CROSS Apply

SELECT 
    who,
    COUNT(id) id
FROM
(SELECT DISTINCT
    MinValues.*
FROM
    INCIDENTS_H h
    CROSS APPLY ( SELECT TOP 1 *
                 FROM INCIDENTS_H h2
                 WHERE h.id = h2.id
                ORDER BY ID, RecNo asc) MinValues) getTheMin
GROUP BY WHO

或者您可以使用Min使用标准SQL John Fisher的答案演示

答案 2 :(得分:1)

应该这样做:

SELECT IH.WHO, COUNT(IH.ID)
FROM INCIDENTS_H IH
JOIN (
  SELECT ID, MIN([Rec No]) [Rec No] 
  FROM INCIDENTS_H
  WHERE ([Type] = 'Assign')
  GROUP BY ID
 ) IH2
 ON IH2.ID = IH.ID AND IH2.[Rec No] = IH.[Rec No]
GROUP BY IH.WHO

答案 3 :(得分:1)

以下是表格中与“首次分配”要求相符的所有内容的视图:

select a.*
from Table.INCIDENTS_H a
inner join
(select ID, min([Rec No]) [Rec No] from Table.INCIDENTS_H where Type = 'Assign' group by ID) b
on a.ID = b.ID and a.[Rec No] = b.[Rec No]

结果:

ID  Rec No  Who Type
1   3   Bob Assign
2   3   John    Assign
3   3   Sarah   Assign

答案 4 :(得分:0)

select * from
  (select
     id, rec_no, who
   from
     operation_history
   where
     type = 'Assign'
   order by rec_no asc) table_alias
group by
  id
order by id asc

经过测试,结果如下:

id  rec_no  who
1      3    Bob
2      3    John
3      3    Sarah

(不是特定于SQL Server的代码)

答案 5 :(得分:0)

以下是原始帖子中提到的虚拟测试数据的查询:

with T (ID,  RecNo,  Who, Type) as
(   
select 1,   1,   'Bob',     'New'   union all
select 1,   2,   'Bob',     'open'  union all
select 1,   3,   'Bob',     'Assign' union all
select 1,   4,   'Sarah',   'Add'   union all
select 1,   5,   'Bob',     'Add'   union all
select 1,   6,   'Bob',     'Close' union all
select 2,   1,   'John',    'New'   union all
select 2,   2,   'John',    'Open'  union all
select 2,   3,   'John',    'Assign' union all
select 2,   4,   'Bob',     'Assign' union all
select 2,   5,   'Sarah',   'Add'   union all
select 2,   6,   'Sarah',   'Close' union all
select 3,   1,   'Sarah',   'New'   union all
select 3,   2,   'Sarah',   'Open'  union all
select 3,   3,   'Sarah',   'Assign' union all
select 3,   4,   'Sarah',   'Close'
)

select top 1 with ties * 
from T
where Type = 'Assign'
order by row_number() over(partition by ID order by RecNo)

可以应用于问题的真实情况的“select”语句可能如下所示:

SELECT TOP 1 WITH TIES 
    IH.ID, IH.[Rec No], IH.WHO, IH.TYPE
FROM Table.INCIDENTS_H IH
WHERE IH.TYPE = 'Assign'
ORDER BY ROW_NUMBER() OVER(PARTITION BY IH.ID ORDER BY IH.[Rec No]);