需要帮助创建复杂的T-SQL SELECT语句

时间:2010-08-10 21:52:29

标签: sql sql-server sql-server-2005 tsql stored-procedures

我正在尝试为以下情况制作SELECT语句,并且需要帮助才能生成此SELECT语句。这是SQL Server 2005。

运行select语句时,假设表中没有重复的PersonID,它应该返回SentDate为NULL的行。它将返回结果集,其状态为“初始记录”(因为尚未发送相同的人员ID)。导出数据后,SentDate将具有今天的日期。

现在假设已添加两个新行且PersonID重复。因此,当语句运行时,它应该仅返回新添加的两条记录,但状态为“跟进记录”,因为在先前的导出作业中导出了相同的人员。

以下是预期的示例:

初始表状态为:

的recordId PERSONID SentDate CreatedDate
1个1 NULL 2010年8月8日
2 2 NULL 2010年8月8日
3 3 NULL 2010年8月8日

首次运行时,应返回以下结果集:

的recordId PERSONID RECORDSTATUS
1 1'初始记录'
2 2'初始记录'
3 3'初始记录'

现在表的状态为:

的recordId PERSONID SentDate CreatedDate
1 1 8/9/2010 2010年8月8日
2 2 8/9/2010 2010年8月8日
3 3 8/9/2010 2010年8月8日

假设稍后在表中添加了一个新表,因此表值将为:

的recordId PERSONID SentDate CreatedDate
1 1 8/9/2010 2010年8月8日
2 2 8/9/2010 2010年8月8日
3 3 8/9/2010 2010年8月8日
4 2 NULL 2010年8月8日
5 2 NULL 2010年8月8日

现在这个查询应该返回

的recordId PERSONID RECORDSTATUS
4 2'跟进记录'
5 2'跟进记录'

2 个答案:

答案 0 :(得分:2)

假设您的表名为Contacts:

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只在表中存在一次,则它是一个初始记录;否则,这是一个跟进记录。

修改

受欢迎的需求,现在减少100%的UNION!

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 :(得分:1)

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