Как использовать агрегатные функции на SQL Сервере - PullRequest
0 голосов
/ 24 февраля 2020

У меня есть ситуация, когда у меня есть таблица Customer, и мне нужно найти номера документов из столбца, который структурирован как строка, где первые 4 символа представляют тип документа (например, «BILL000000000001», «PYMT000000000001») , Каждый из этих документов также имеет соответствующую дату документа. Я хочу получить CustomerNumber , где DocType равен BILL с max (DocDate) и вернуть CustomerNumber и DocDate . Эта часть довольно проста и не представляет трудностей.

Моя проблема в том, что у некоторых клиентов еще нет документа, начинающегося с BILL. Для них я хочу получить CustomerNumber и max (DocDate) , который соответствует другой строке XXXX в качестве первых 4 символов. По сути, мне нужно использовать какое-то условное выражение, которое выбирает либо CustomerNumber и max (DocDate) для типа BILL, либо Customer Number и max (DocDate) для типа записи XXXX . Проблема в том, что существует вероятность того, что для Клиента могут существовать типы BILL и XXXX . Если существует BILL , я хочу выбрать CustomerNumber и max (DocDate) для этого клиента. Однако, если существует тип XXXX , но нет документа типа BILL , мне нужны CustomerNumber и max (DocDate) для типа XXXX .

Я думал об использовании EXCEPT и UNION , но я не думаю, что какой-либо вариант действительно работает для меня. Вот мой SQL с ИСКЛЮЧИТЬ , если это вообще поможет.

select CustomerNumber, max(DocDate)
FROM Table1
where substring(DocumentNumber,1,4) = 'BILL'
group by CustomerNumber
EXCEPT
select CustomerNumber, max(DocDate)
from Table1
where substring(umDocumentNumber,1,4) = 'MISC'
group by CustomerNumber

Ответы [ 2 ]

3 голосов
/ 24 февраля 2020

Вы можете делать что хотите, используя агрегацию:

select CustomerNumber,
       coalesce(max(case when DocumentNumber like 'BILL%' then DocDate end),
                max(DocumentNumber)
               )
from Table1
where DocumentNumber like 'BILL%' or DocumentNumber like 'MISC%'
group by CustomerNumber;

Или используя оконные функции:

select t1.*
from (select t1.*,
             row_number() over (partition by CustomerNumber
                                order by left(DocumentNumber, 4), DocDate desc
                               ) as seqnum
      from Table1 t1
     ) t1
where seqnum = 1;

Этот метод позволяет вернуть всю строку для максимального документа.

2 голосов
/ 24 февраля 2020

Если я понимаю вашу логику c, вам нужны CustomerNumber и MAX(DocDate) для клиентов, имеющих запись типа BILL, а также CustomerNumber и MAX(DocDate) для любых клиентов, у которых Запись типа BILL не существует.

UNION ваших начальных результатов и другой набор результатов, который включает в себя предложение WHERE NOT EXISTS, должно вернуть то, что вы ищете.

SELECT 
   CustomerNumber
    ,max(DocDate)
FROM Table1
WHERE substring(DocumentNumber, 1, 4) = 'BILL'
GROUP BY CustomerNumber

UNION ALL

SELECT 
   CustomerNumber
    ,max(DocDate)
FROM Table1 AS out
WHERE 
  NOT EXISTS (SELECT 1
              FROM Table1 AS in
              WHERE 
                in.CustomerNumber = out.CustomerNumber
                AND
                substring(umDocumentNumber, 1, 4) = 'BILL'
GROUP BY CustomerNumber;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...