【问题标题】:Need help creating complex T-SQL SELECT statement需要帮助创建复杂的 T-SQL SELECT 语句
【发布时间】:2010-08-10 21:52:28
【问题描述】:

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

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

现在假设添加了两个新行并且 PersonID 是重复的。因此,当语句运行时,它应该只返回新添加的两条记录,但状态为“Follow up Record”,因为在之前的导出作业中导出了相同的人。

这是预期的示例:

初始表状态为:

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

第一次运行时,它应该返回以下结果集:

RecordId  PersonId  RecordStatus
1  1  '初始记录'
2  2  '初始记录'
3  3  '初始记录'

现在表格的状态将是:

RecordId  PersonId  SentDate  CreatedDate
1  1  2010 年 8 月 9 日  2010 年 8 月 8 日
2  2  2010 年 8 月 9 日  2010 年 8 月 8 日
3  3  2010 年 8 月 9 日  2010 年 8 月 8 日

假设稍后在 table 中添加了一个新的,因此 table 值将是:

RecordId  PersonId  SentDate  CreatedDate
1  1  2010 年 8 月 9 日  2010 年 8 月 8 日
2  2  2010 年 8 月 9 日  2010 年 8 月 8 日
3  3  2010 年 8 月 9 日  2010 年 8 月 8 日
4  2  空  8/8/2010
5  2  空  8/8/2010

现在这个查询应该返回

RecordId  PersonId  RecordStatus
4  2  '跟进记录'
5  2  '跟进记录'

【问题讨论】:

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


    【解决方案1】:

    假设您的表名为联系人:

    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 
    

    【讨论】:

      【解决方案2】:
      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-09-27
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多