【问题标题】:SQL - Retrieve Unique Values of single column where by multiple columns may be uniqueSQL - 检索单列的唯一值,其中多列可能是唯一的
【发布时间】:2017-11-22 08:41:31
【问题描述】:

我试图只返回唯一的“参考”,但还需要撤回可能也是唯一的“姓氏”和“电子邮件”。在我的示例中,您可以将多个客户关联到一个参考。目前,我的查询拉回了与“参考”关联的所有客户。由于我只需要其中一位客户的详细信息,因此我只想使用“姓氏”和“电子邮件”撤回“参考”一次。

以下查询是一个示例,但它与我想要实现的场景有关。

在示例中,“UniqueID”本质上是项目添加到表中的顺序。我需要这个,所以我可以按最近的记录进行过滤。由于“参考”不是基于增量的,我不能使用它。

所以,本质上我想计算有多少重复的“参考”实例,但只返回一个“参考”实例加上相应的“电子邮件”和“姓氏”,然后按添加的最新记录排序。

每张桌子的味道:

CustomerPackage: UniqueID (INT); Reference (STRING)
Customer: FirstName (STRING); Surname (STRING); Email (STRING); Address (STRING)
PurchaseDetails: PurchaseDate (DATE); PurchaseDescription (STRING); PurchaseType (INT)

SQL 脚本示例:

USE Example
GO

SELECT TOP 10

CP.Reference,
C.Surname,
C.Email

FROM CustomerPackage CP

INNER JOIN Customer C ON CP.UniqueID = C.UniqueID
INNER JOIN PurchaseDetails PD ON CP.UniqueID = PD.UniqueID

WHERE PD.PurchaseDate > dateadd(HOUR,10,getutcdate()) and PD.PurchaseDate < dateadd(DAY,29,getutcdate()) and PD.PurchaseType = 1

ORDER BY CP.UniqueID DESC

输出:

Reference   Surname     Email
1XX45       Smith       e.e@e.com
1XX45       Jones       f.f@f.com
1XX45       Betty       g.g@g.com
4B678       Reeds       h.h@h.com

=========================

需要的输出:

Reference   Surname     Email
1XX45       Smith       e.e@e.com
4B678       Reeds       h.h@h.com

【问题讨论】:

  • 为什么选择电子邮件e.e@e.com 而不是其他两个的逻辑是什么?
  • 没有逻辑,只是可以选择任何重复的引用。只要只返回一个引用
  • 那么您有以下两个有效的答案可供选择。

标签: sql sql-server count distinct


【解决方案1】:

我认为你缺少的只是Row_Number

;WITH cteX
AS(
    SELECT TOP 10
    RN = ROW_NUMBER()OVER(PARTITION BY CP.Reference ORDER BY CP.UniqueId DESC),
    CP.Reference,
    C.Surname,
    C.Email,
    CP.UniqueId

    FROM CustomerPackage CP

    INNER JOIN Customer C ON CP.UniqueID = C.UniqueID
    INNER JOIN PurchaseDetails PD ON CP.UniqueID = PD.UniqueID

    WHERE PD.PurchaseDate > dateadd(HOUR,10,getutcdate()) and PD.PurchaseDate < dateadd(DAY,29,getutcdate()) and PD.PurchaseType = 1
)
SELECT
    Reference
    ,Surname
    ,Email
FROM cteX X
WHERE X.RN = 1
ORDER BY UniqueId DESC

【讨论】:

    【解决方案2】:

    如果您想要的是每个参考记录组的最近购买日期的单个记录,那么您可以使用ROW_NUMBER

    SELECT Reference, Surname, Email
    FROM
    (
        SELECT
            CP.Reference,
            CP.UniqueID,
            C.Surname,
            C.Email,
            ROW_NUMBER() OVER (PARTITION BY CP.Reference ORDER BY PD.PurchaseDate DESC) rn
        FROM CustomerPackage CP
        INNER JOIN Customer C
            ON CP.UniqueID = C.UniqueID
        INNER JOIN PurchaseDetails PD
            ON CP.UniqueID = PD.UniqueID
        WHERE
            PD.PurchaseDate > dateadd(HOUR,10,getutcdate()) AND
            PD.PurchaseDate < dateadd(DAY,29,getutcdate()) AND
            PD.PurchaseType = 1
    ) t
    WHERE rn = 1
    ORDER BY
        UniqueID DESC;
    

    【讨论】:

    • 在所有答案中提供了这个有效的答案。我认为其他人也可以工作,但由于表的大小,其他查询花费的时间太长。这个只用了 28 秒就跑完了。谢谢
    【解决方案3】:

    您要查找的内容称为 GROUP BY 条件。在您的情况下,您希望按 CP.Reference 进行分组。这将汇总每个参考的所有数据。这样做的结果是您的查询将不知道要为姓氏和电子邮件显示哪些数据(1XX45 有 3 个不同的姓氏和电子邮件)。在您的情况下,您只想显示一个姓氏或电子邮件,这样您就可以选择这些记录中的最高值。您的查询将变为:

    USE Example
    GO
    
    SELECT TOP 10
    
    CP.Reference,
    MAX(C.Surname),
    MAX(C.Email)
    
    FROM CustomerPackage CP
    
    INNER JOIN Customer C ON CP.UniqueID = C.UniqueID
    INNER JOIN PurchaseDetails PD ON CP.UniqueID = PD.UniqueID
    
    WHERE PD.PurchaseDate > dateadd(HOUR,10,getutcdate()) and PD.PurchaseDate < dateadd(DAY,29,getutcdate()) and PD.PurchaseType = 1
    ORDER BY CP.UniqueID DESC
    GROUP BY CP.Reference
    

    【讨论】:

    • 这种方法在实践中可能行不通,因为 max surname 和 max email 可能并不总是对应相同的记录。并且预期的输出无论如何都暗示着最少的电子邮件。
    猜你喜欢
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多