Как использовать SUM, LEFT JOIN, group by и order by в одном SQL-операторе

#sql #sql-server #tsql #group-by #sum

#sql #sql-сервер #tsql #группировка по #сумма

Вопрос:

Я пытаюсь создать запрос, который я могу использовать в своем ASP.NET код, который извлекается из базы данных и затем экспортируется в файл Excel. Моя цель — заставить SQL выполнять большую часть работы, прежде чем я перейду к своему рабочему листу. Это мой код перед использованием sum и group by

 SELECT EOD_Rental_Fees.*, POSH5_Prod_CoreBankingDetails.description as TotalFeeAmount)
FROM EOD_Rental_Fees
LEFT JOIN POSH5_Prod_CoreBankingDetails ON EOD_Rental_Fees.CoreBankingID = POSH5_Prod_CoreBankingDetails.ID 
WHERE DateProcessed >= '2018-07-01 00:00:00.000'
AND DateProcessed <= '2018-08-30 00:00:00:000'          
ORDER BY description, DateProcessed;
 

Это и есть результат этого:введите описание изображения здесь

Когда я добавляю SUM или GROUP BY вот так

  Select  EOD_Rental_Fees.*, POSH5_Prod_CoreBankingDetails.description, (Select SUM (EOD_Rental_Fees.TotalFee) as TotalFeeAmount) from 
            EOD_Rental_Fees
            LEFT JOIN POSH5_Prod_CoreBankingDetails ON EOD_Rental_Fees.CoreBankingID = POSH5_Prod_CoreBankingDetails.ID 
            WHERE DateProcessed >= '2018-07-01 00:00:00.000'
            AND DateProcessed <= '2018-08-30 00:00:00:000'
            Group By Currency
            Order By description, DateProcessed;
 

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

Чего я пытаюсь достичь, это что-то вроде этого:

введите описание изображения здесь

Комментарии:

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

2. Необходимо знать, какую базу данных вы используете, и версию, ни один из выбранных тегов не сужает возможности решения в достаточной степени. например, MySQL 8 будет отличаться от MySQL 5x

3. Извиняюсь, я добавил sql-server к тегам. Спасибо!

4. что такое SUM (EOD_Rental_Fees. Отображается totalFee)? группировка по валюте не имеет смысла

5. Пожалуйста, отправьте код, данные и ошибки в виде форматированного текста, а не изображений.

Ответ №1:

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

«Из того, что я вижу, мой запрос выглядит нормально» Извините, это не нормально, потому что это приводит к ошибкам SQL. Эта ошибка фактически говорит вам, что если вы хотите использовать group by, вы должны указать, по каким столбцам группироваться. Ваш запрос этого не делает.

Чтобы избежать этой ошибки, каждый «неагрегирующий» столбец должен быть указан в предложении group by следующим образом (обратите внимание, что вы не можете использовать * для этого)

 SELECT 
      rf.id
    , rf.year
    , rf.month
    , rf.DateProcessed
    , rf.CoreBankingID
    , rf.MerchantRecordID
    , rf.DeployedDate 
    , rf.TerminalRecordID
    , rf.DeployedDate
    , rf.RecoveredDate
    , rf.MonthlyFee
    , rf.IsProRated
    , rf.DaysActive
    , rf.TotalFee
    , rf.IsPinPad
    , rf.Currency
    , det.description
    , sum(rf.TotalFee) as TotalFeeAmount
FROM EOD_Rental_Fees AS rf
LEFT JOIN POSH5_Prod_CoreBankingDetails as det ON rf.CoreBankingID = det.ID
WHERE rf.DateProcessed >= '2018-07-01 00:00:00.000'
   AND rf.DateProcessed < '2018-09-01 00:00:00:000'
GROUP BY
      rf.id
    , rf.year
    , rf.month
    , rf.DateProcessed
    , rf.CoreBankingID
    , rf.MerchantRecordID
    , rf.DeployedDate 
    , rf.TerminalRecordID
    , rf.DeployedDate
    , rf.RecoveredDate
    , rf.MonthlyFee
    , rf.IsProRated
    , rf.DaysActive
    , rf.TotalFee
    , rf.IsPinPad
    , rf.Currency
    , det.description
ORDER BY
      det.description
    , rf.DateProcessed
 

Однако я подозреваю, что это не приведет к желаемому результату, потому что вам нужны как детали, так и резюме одновременно, что GROUP BY не предназначено для достижения.

Я думаю, вы обнаружите, что использование SUM() OVER() будет ближе к тому, что вам нужно, но как именно вам нужно PARTITION BY , чтобы подпункт работал, мне не ясно. несмотря на это, это может сработать для вас:

 SELECT 
      rf.id
    , rf.year
    , rf.month
    , rf.DateProcessed
    , rf.CoreBankingID
    , rf.MerchantRecordID
    , rf.DeployedDate 
    , rf.TerminalRecordID
    , rf.DeployedDate
    , rf.RecoveredDate
    , rf.MonthlyFee
    , rf.IsProRated
    , rf.DaysActive
    , rf.TotalFee
    , rf.IsPinPad
    , rf.Currency
    , det.description
    , sum(rf.TotalFee) over(partition by rf.CoreBankingID, Currency) as TotalFeeAmount
FROM EOD_Rental_Fees AS rf
LEFT JOIN POSH5_Prod_CoreBankingDetails as det ON rf.CoreBankingID = det.ID
WHERE rf.DateProcessed >= '2018-07-01 00:00:00.000'
   AND rf.DateProcessed < '2018-09-01 00:00:00:000'
ORDER BY
      det.description
    , rf.DateProcessed
    
 

Примечания:

  1. Используйте псевдонимы таблиц для упрощения ваших запросов
  2. при объединении таблиц включите псевдонимы таблиц во все ссылки на столбцы
  3. Я слегка изменил способ работы с диапазоном дат, всегда используйте комбинацию >= с <, а верхняя граница — «на следующий день». При таком подходе вы покрываете себя для любых строк данных, которые содержат как дату, так и время.

Комментарии:

1. Привет, большое спасибо! Я продолжал добавлять к нему, чтобы предоставить больше деталей и облегчить людям понимание того, что я искал. Извините за это!

2. Пожалуйста, обратите внимание на изменение диапазона дат в предложении where. При работе с данными datetime легко допустить ошибки, которые могут исключить продолжительность последнего дня.

Ответ №2:

вот как вы можете это сделать, используя GROUP BY ROLLUP :

 Select
    DESCRIPTION
    , currency
    , DateProcessed 
    SUM (EOD_Rental_Fees.TotalFee)
from
    EOD_Rental_Fees
LEFT JOIN POSH5_Prod_CoreBankingDetails 
    ON EOD_Rental_Fees.CoreBankingID = POSH5_Prod_CoreBankingDetails.ID
WHERE
    DateProcessed >= '2018-07-01 00:00:00.000'
    AND DateProcessed <= '2018-08-30 00:00:00:000'
GROUP BY ROLLUP (DESCRIPTION, currency, DateProcessed)
Order By
    description,DateProcessed;