#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. Пожалуйста, обратите внимание на изменение диапазона дат в предложении 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;