SQL-запрос для поиска репрезентативных строк в таблице - PullRequest
2 голосов
/ 17 декабря 2008

Допустим, у меня есть таблица платежей примерно так:

PaymentID INT, CustomerID INT, Значение INT, Оплачено ДАТА

И я хочу выполнить запрос на максимальный платеж, сделанный каждым клиентом. Возможно ли это с помощью одного SQL-запроса, чтобы избежать необходимости перебирать каждую строку, которая мне не интересна, или, что еще хуже, запускать запрос для каждого клиента?

Лучшее, что я до сих пор придумал, это:

ВЫБЕРИТЕ CustomerID, MAX (значение) ОТ платежа GROUP BY CustomerID;

Но это не дает мне значения PaymentId или PaidOn для строк, которые он находит.

Ответы [ 5 ]

10 голосов
/ 17 декабря 2008
select PaymentID, CustomerID, Value, PaidOn
from payments
where (customerID, value) in
( select customerID, max(value)
  from payments 
  group by customerID
);

Обратите внимание, что это может возвратить более одной строки на клиента, если у них более одного платежа с максимальным значением.

4 голосов
/ 17 декабря 2008

Этот вопрос в значительной степени идентичен этому с более раннего сегодняшнего дня.

Чтобы избежать подзапросов, вы также можете использовать:

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
2 голосов
/ 17 декабря 2008

Следующий запрос выполнит это. Он вытягивает все строки, для которых значение не больше.

SELECT *
FROM payments p
WHERE NOT EXISTS (
    SELECT *
    FROM payments p2
    WHERE p2.CustomerID = p.CustomerId
    AND   p2.Value > p.Value
)
0 голосов
/ 17 декабря 2008

Вот один вариант, который использует производную таблицу:

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
0 голосов
/ 17 декабря 2008

Еще одно использование Self join - вопрос синтаксического сахара. Легче понять и хорошо по производительности.

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

-Маулик Моди

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...