SQL - найти уникальное минимальное значение и связанные столбцы - PullRequest
3 голосов
/ 21 июня 2011

У меня есть набор данных, как показано ниже, показывающий историю того, кто что сделал с записью. Уникальный идентификатор для каждой записи отображается в «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

Мне нужно найти все операции «Назначить». Однако, если несколько «Назначить» находятся в определенном идентификаторе, я хочу найти первый. Затем я также хочу найти имя человека, который это сделал.

Таким образом, в конечном итоге с указанной даты я бы хотел, чтобы результат был ...

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

Как выяснилось, Боб сделал присвоение по идентификатору 2, запись № 4.

Любая помощь будет оценена. Я использую MS SQL.

Ответы [ 6 ]

1 голос
/ 21 июня 2011

Вот представление всего, что в таблице соответствует вашему требованию «первое назначение»:

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
1 голос
/ 21 июня 2011

Это должно сделать это:

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
1 голос
/ 21 июня 2011

Вы можете использовать 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, ответ Джона Фишера демонстрирует

1 голос
/ 21 июня 2011

Я думаю, что-то вроде того, что вы ищете:

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

Это должно учитывать только первое назначение (упорядоченное по Rec) в каждой группе идентификаторов.

0 голосов
/ 22 июня 2011

Вот запрос с данными виртуального теста, которые были упомянуты в оригинальном сообщении:

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]);
0 голосов
/ 21 июня 2011
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)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...