Запрос совокупной суммы в таблице SQL с отдельными элементами

У меня есть такая таблица с именами столбцов как Дата продажи и страховкой Имена продавцов -

Date of Sale | Salesman Name | Sale Amount
2021-03-01   | Jack          | 40  
2021-03-02   | Mark          | 60
2021-03-03   | Sam           | 30 
2021-03-03   | Mark          | 70 
2021-03-02   | Sam           | 100

Я хочу сделать группу, используя дату продажи. В следующем столбце должно отображаться общее количество продавцов, совершивших продажу до этой даты. Но одни и те же продавцы не должны рассматриваться снова.

Например, следующая таблица неверна,

Date of Sale | Count(Salesman Name) | Sum(Sale Amount)
2021-03-01   | 1                    | 40
2021-03-02   | 3                    | 200
2021-03-03   | 5                    | 300  

Следующая таблица верна,

Date of Sale | Count(Salesman Name) | Sum(Sale Amount)
2021-03-01   | 1                    | 40
2021-03-02   | 3                    | 200
2021-03-03   | 3                    | 300

Я не уверен, как сформулировать SQL-запрос, потому что здесь задействованы два условия: кумулятивный подсчет при игнорировании дубликатов. Я думаю, что предложение OVER вместе с предшествующей неограниченной строкой может быть здесь полезным? Запросить вашу помощь

Изменить - я добавил сумму продажи в виде столбца. Мне также нужна совокупная сумма для суммы продаж. Но в этом случае следует учитывать все суммы продаж, в отличие от случая с именем продавца, где учитывались только уникальные имена.


person Dawson Smith    schedule 01.05.2021    source источник
comment
Укажите используемые вами СУБД. Разные поставщики поддерживают разные функции.   -  person NineBerry    schedule 01.05.2021


Ответы (2)


Один подход использует самообъединение и агрегацию:

WITH cte AS (
    SELECT t1.SaleDate,
           COUNT(CASE WHEN t2.Salesman IS NULL THEN 1 END) AS cnt,
           SUM(t1.SaleAmount) AS amt
    FROM yourTable t1
    LEFT JOIN yourTable t2
        ON t2.Salesman = t1.Saleman AND
           t2.SaleDate < t1.SaleDate
    GROUP BY t1.SaleDate
)

SELECT
    SaleDate,
    SUM(cnt) OVER (ORDER BY SaleDate) AS NumSalesman,
    SUM(amt) OVER (ORDER BY SaleDate) AS TotalAmount
FROM cte
ORDER BY SaleDate;

Логика CTE заключается в том, что мы пытаемся найти для каждого продавца более раннюю запись для того же самого продавца. Если мы не можем найти такую ​​запись, мы предполагаем, что рассматриваемая запись является первой. Затем мы агрегируем по дате, чтобы получить счетчики за день, и, наконец, получаем скользящую сумму счетчиков во внешнем запросе.

person Tim Biegeleisen    schedule 01.05.2021
comment
Эй, Тим, спасибо за ответ. Я добавил еще один столбец в свою таблицу. Можете ли вы предложить изменения, которые необходимо внести в ваш запрос для включения столбца суммы продаж? - person Dawson Smith; 01.05.2021
comment
Кстати, спасибо за прекрасное объяснение. - person Dawson Smith; 01.05.2021
comment
Эй, будут ли игнорироваться повторяющиеся имена продавцов, но не будут игнорироваться строки суммы продаж? - person Dawson Smith; 01.05.2021
comment
Конечно, приму ответ, как только проблема будет решена - person Dawson Smith; 01.05.2021
comment
Проблема решена, перезагрузите страницу. - person Tim Biegeleisen; 01.05.2021
comment
Не будут ли игнорироваться в моей таблице такие суммы, как 70 и 100? - person Dawson Smith; 01.05.2021
comment
Сначала вы должны попробовать мой обновленный ответ, а затем задать вопросы об этом. - person Tim Biegeleisen; 01.05.2021
comment
Привет Тим, это не работает. Отображаются результаты только до 2 марта - person Dawson Smith; 01.05.2021
comment
Я добавил скриншот в ваш ответ, пожалуйста, проверьте. Я написал тот же запрос, что и вы - person Dawson Smith; 01.05.2021
comment
Эй, я хотел бы предложить небольшое редактирование. Эта строка выдает неправильный результат -> СУММА (СЛУЧАЙ, КОГДА t2.Salesman IS NULL THEN t1.SaleAmount ELSE 0 END) AS amt. Можем ли мы заменить его, используя просто SUM(t1.SaleAmount)? - person Dawson Smith; 01.05.2021
comment
Окончательный результат неверен. На 3 марта результат, который я получаю, равен 200, хотя на самом деле он должен быть 300. - person Dawson Smith; 01.05.2021
comment
Вы правы... Я думаю, вам просто нужна безусловная сумма суммы продаж. - person Tim Biegeleisen; 01.05.2021
comment
Да, значит, изменение, которое я предложил, подходит? Или еще что-то требуется? Просим вас обновить свой ответ соответствующим образом - person Dawson Smith; 01.05.2021
comment
Эй, Тим, а что, если у одной даты может быть несколько вхождений одного и того же имени, как это устранить? - person Dawson Smith; 02.05.2021
comment
Запрос завершается ошибкой, если одна дата может иметь несколько вхождений одного и того же имени. - person Dawson Smith; 02.05.2021
comment
Я не знаю, что сказать, потому что я не вижу этих новых данных. Я предлагаю вам открыть новый вопрос на этом этапе. Пожалуйста, не редактируйте свой вопрос снова. - person Tim Biegeleisen; 02.05.2021
comment
Хорошо, я задам новый вопрос. Вы можете помочь мне с этим? - person Dawson Smith; 02.05.2021
comment
Просто покажите четкие данные вместе с тем, какой результат вы хотите. Это позволяет избежать многократных проверок. - person Tim Biegeleisen; 02.05.2021
comment
stackoverflow.com/questions/67355357/ - person Dawson Smith; 02.05.2021
comment
Привет Тим. Не могли бы вы помочь мне с моим новым вопросом? - person Dawson Smith; 05.05.2021

Лучший способ сделать это — использовать оконные функции для определения первого появления продавца. Затем вам просто нужны кумулятивные суммы:

select saledate,
       sum(case when seqnum = 1 then 1 else 0 end) over (order by saledate) as num_salespersons,
       sum(sum(sales)) over (order by saledate) as running_sales
from (select t.*,
             row_number() over (partition by salesperson order by saledate) as seqnum
      from t
     ) t
group by saledate
order by saledate;

Обратите внимание, что это не только более лаконично, но и должно иметь гораздо лучшую производительность, чем решение, использующее самообъединение.

person Gordon Linoff    schedule 01.05.2021
comment
Эй, спасибо за этот ответ, Гордон. Предоставляет совершенно новый способ решения сложного запроса. Любые хорошие ресурсы для изучения оконных функций? - person Dawson Smith; 01.05.2021
comment
Я бы посоветовал вам начать с документации по базе данных, которую вы используете. - person Gordon Linoff; 01.05.2021