【问题标题】:SQL query for finding representative rows in a table用于在表中查找代表性行的 SQL 查询
【发布时间】:2010-09-27 09:04:04
【问题描述】:

假设我有一个这样的付款表:

付款ID INT, 客户 ID INT, 值 INT, 付款日期

我想查询每个客户支付的最高金额。这是否可以使用单个 SQL 查询来避免不得不挖掘我不感兴趣的每一行——或者更糟的是,为每个客户运行一个查询?

到目前为止,我想出的最好的是:

SELECT CustomerID, MAX(Value) FROM Payments GROUP BY CustomerID;

但这并没有给我它找到的行的 PaymentId 或 PaidOn 值。

【问题讨论】:

    标签: sql


    【解决方案1】:

    以下查询将完成此操作。它会拉出所有没有更大值的行。

    SELECT *
    FROM payments p
    WHERE NOT EXISTS (
        SELECT *
        FROM payments p2
        WHERE p2.CustomerID = p.CustomerId
        AND   p2.Value > p.Value
    )
    

    【讨论】:

    • 这可能不会像 Tony Andrew 那样好,因为必须为每个客户运行子查询。
    【解决方案2】:
    select PaymentID, CustomerID, Value, PaidOn
    from payments
    where (customerID, value) in
    ( select customerID, max(value)
      from payments 
      group by customerID
    );
    

    请注意,如果每位客户有超过一笔最高金额的付款,这可能会返回多于一行。

    【讨论】:

      【解决方案3】:

      另一个使用自连接 - 语法糖的问题。更易于理解且性能良好。

      select PaymentID, CustomerID, Value, PaidOn
      from
      ( select customerID, max(value) as maxValue
        from payments 
        group by customerID
      )as T
       INNER JOIN payments as P
        ON P.Value=T.maxValue AND P.CustomerID = T.CustomerID
      

      -莫利克·莫迪

      【讨论】:

        【解决方案4】:

        这是一个使用派生表的选项:

        SELECT     p2.PaymentId, p2.CustomerID, p2.Value, p2.PaidOn
        FROM         Payments AS p2 INNER JOIN
            (SELECT     CustomerID, MAX(Value) AS Value
             FROM          Payments
             GROUP BY CustomerID)
        AS p1
        ON p1.CustomerID = p2.CustomerID AND p1.Value = p2.Value
        

        【讨论】:

          【解决方案5】:

          这与今天早些时候的this one 几乎是一个相同的问题。

          为避免子查询,您还可以使用:

          SELECT
               P1.PaymentID,
               P1.CustomerID,
               P1.Value,
               P1.PaidOn
          FROM
               Payments P1
          LEFT OUTER JOIN Payments P2 ON
               P2.CustomerID = P1.CustomerID AND
               P2.Value > P1.Value
          WHERE
               P2.PaymentID IS NULL
          

          根据您需要更改此查询的值的关联业务规则。

          例如,如果出现平局,则使用最新付款:

          SELECT
               P1.PaymentID,
               P1.CustomerID,
               P1.Value,
               P1.PaidOn
          FROM
               Payments P1
          LEFT OUTER JOIN Payments P2 ON
               P2.CustomerID = P1.CustomerID AND
               (P2.Value > P1.Value OR (P2.Value = P1.Value AND P2.PaidOn > P1.PaidOn))
          WHERE
               P2.PaymentID IS NULL
          

          【讨论】:

          • 现在是一个有争议的问题,但这不是一个相同的问题,即使答案非常相似。在今天早些时候的一个中,没有要求记录是最高金额。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2017-08-30
          • 2018-07-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-09-04
          • 2020-06-14
          相关资源
          最近更新 更多