Нужна помощь в создании сложного оператора T-SQL SELECT - PullRequest
1 голос
/ 11 августа 2010

Я пытаюсь сделать оператор SELECT для следующей ситуации, и мне нужна помощь, чтобы сделать этот оператор SELECT. Это SQL Server 2005.

Когда выполняется оператор select, он должен возвращать строки с SentDate как NULL, при условии, что в таблице нет повторяющихся PersonID. Он вернет набор результатов со статусом «Начальная запись» (так как тот же идентификатор человека еще не был отправлен). После экспорта данных SentDate будет иметь сегодняшнюю дату.

Теперь предположим, что две новые строки были добавлены, а PersonID дублирован. Поэтому, когда оператор выполняется, он должен возвращать только недавно добавленные две записи, но иметь статус «Последующая запись», потому что этот же человек был экспортирован в предыдущем задании экспорта.

Вот пример того, что ожидается:

Исходное состояние таблицы будет:

RecordId PersonId SentDate CreatedDate
1 1 NULL 8/8/2010
2 2 NULL 8/8/2010
3 3 NULL 8/8/2010

При первом запуске он должен вернуть следующий набор результатов:

RecordId PersonId RecordStatus
1 1 «Начальная запись»
2 2 'Начальная запись'
3 3 'Начальная запись'

Теперь состояние таблицы будет:

RecordId PersonId SentDate CreatedDate
1 1 8/9/2010 8/8/2010
2 2 8/9/2010 8/8/2010
3 3 8/9/2010 8/8/2010

Предположим, позже в таблицу было добавлено новое значение, поэтому значения таблицы будут:

RecordId PersonId SentDate CreatedDate
1 1 8/9/2010 8/8/2010
2 2 8/9/2010 8/8/2010
3 3 8/9/2010 8/8/2010
4 2 NULL 8/8/2010
5 2 NULL 8/8/2010

Теперь этот запрос должен вернуть

RecordId PersonId RecordStatus
4 2 'Follow Record'
5 2 'Follow Record'

Ответы [ 2 ]

2 голосов
/ 11 августа 2010

Предполагается, что ваша таблица называется Контакты:

SELECT RecordId, C1.PersonId, 'Initial Record' AS RecordStatus
FROM Contacts C1
INNER JOIN (SELECT PersonId, COUNT(PersonId) as PersonCount 
            FROM Contacts 
            GROUP BY PersonId) C2 ON
 C1.PersonId = C2.PersonId
WHERE SentDate IS NULL AND PersonCount = 1

UNION

SELECT RecordId, C1.PersonId, 'Follow Up Record' AS RecordStatus
FROM Contacts C1
INNER JOIN (SELECT PersonId, COUNT(PersonId) as PersonCount 
            FROM Contacts 
            GROUP BY PersonId) C2 ON
 C1.PersonId = C2.PersonId
WHERE SentDate IS NULL AND PersonCount > 1

ORDER BY RecordId

Запрос работает, предполагая, что если PersonId существует только один раз в таблице, это начальная запись;в противном случае, это запись о последующих действиях.

РЕДАКТИРОВАТЬ

По многочисленным просьбам, теперь с UNION на 100% меньше!

SELECT RecordId, C1.PersonId, 
 CASE WHEN PersonCount > 1 THEN 'Follow Up Record' 
 WHEN PersonCount = 1 THEN 'Initial Record' END
 AS RecordStatus
FROM Contacts C1
INNER JOIN (SELECT PersonId, COUNT(PersonId) as PersonCount 
            FROM Contacts
            GROUP BY PersonId) C2 ON
    C1.PersonId = C2.PersonId
WHERE SentDate IS NULL

РЕДАКТИРОВАТЬ 2

Это, вероятно, излишне, но вот мой первый выстрел в версии CTE:

With PersonCountCTE (PersonId, PersonCount) AS 
(
    SELECT PersonId, COUNT(PersonId) AS PersonCount
    FROM Contacts 
    GROUP BY PersonId
)
SELECT RecordId, C1.PersonId, 
    CASE WHEN PersonCount > 1 THEN 'Follow Up Record' 
    WHEN PersonCount = 1 THEN 'Initial Record' END
    AS RecordStatus
FROM Contacts C1 
INNER JOIN PersonCountCTE C2 ON C1.PersonId = C2.PersonId
WHERE SentDate IS NULL 
1 голос
/ 11 августа 2010
With Data As
    (
    Select RecordId, PersonId, SentDate, CreatedDate
        , Row_Number() Over ( Partition By PersonId 
                              Order By CreatedDate Desc, RecordId Desc ) As Seq
    From #Test
    )
Select RecordId, PersonId
    , Case 
        When Seq = 1 Then 'Initial Record'
        Else 'Follow up Record'
        End As RecordStatus
From Data
Where SentDate Is Null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...