Запрос возвращает неверную ошибку в столбце, который уже существует?

Я хочу сгруппировать по дате и платежу, а также названию и коду филиала. Я не знаю, почему этот SQL-запрос возвращает эту ошибку:

Столбец «FactSalesTable.SalesTotal» недопустим в списке выбора, поскольку он не содержится ни в агрегатной функции, ни в предложении GROUP BY.

SELECT 
    FactSalesTable.Date,
    FactSalesTable.PaymentID,
    Branch.* ,
    SUM(FactSalesTable.SalesTotal) AS TotalSales,
    AVG (FactSalesTable.SalesTotal) OVER (PARTITION BY Branch.BCode) AS AvgSales,
    CASE
        WHEN SUM(FactSalesTable.SalesTotal) OVER (PARTITION BY Branch.BCode) /AVG(FactSalesTable.SalesTotal) OVER (PARTITION BY Branch.BCode) > 1 THEN 'Above Avg' 
        WHEN SUM(FactSalesTable.SalesTotal) OVER (PARTITION BY Branch.BCode)/AVG(FactSalesTable.SalesTotal) OVER (PARTITION BY Branch.BCode) = 1 THEN 'Avg'
        ELSE 'Below Avg'
    END AS SalesResult
FROM Branch
LEFT JOIN FactSalesTable ON Branch.BCode = FactSalesTable.BCode
WHERE FactSalesTable.SalesTotal > 0 AND Branch.BCode = 1021
GROUP BY FactSalesTable.Date, Branch.BranchName, Branch.BCode, FactSalesTable.PaymentID
ORDER BY FactSalesTable.Date DESC

Я хочу показать общий объем продаж по дате, например

дата БКод общий объем продаж среднее 2023-04-30 1021 4333 5050 30 апреля 2022 г. 1021 6392 5050 2022-04-29 1021 3544 5050 2022-04-29 1021 2300 5050

Это фрагмент запроса без группы по

Из-за ваших оконных агрегатов. Данные о расходных образцах (не изображения) и ожидаемые результаты помогут нам помочь вам.

Thom A 30.08.2024 16:25

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

Joel Coehoorn 30.08.2024 16:28

Поместите запрос, за исключением AVG, в подзапрос, и тогда вы сможете усреднить по своему усмотрению. Однако согласен с предыдущими ораторами, публиковать выходные данные вашего запроса бессмысленно (и еще хуже, когда он в форме изображения), что помогает, так это ввод и ожидаемый результат.

siggemannen 30.08.2024 16:39

моя ошибка, я добавил примеры данных

Ahmed 30.08.2024 16:40

Эта скрипта может помочь нам совместно найти решение dbfiddle.uk/W7JahRBD

Bart McEndree 30.08.2024 16:43
ReactJs | Supabase | Добавление данных в базу данных
ReactJs | Supabase | Добавление данных в базу данных
Это и есть ваш редактор таблиц в supabase.👇
Понимание Python и переход к SQL
Понимание Python и переход к SQL
Перед нами лабораторная работа по BloodOath:
1
5
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы агрегируете данные на двух уровнях:

  1. Обычная агрегация SUM(SalesTotal) для каждого отделения и платежа, как определено в GROUP BY.
  2. Оконная агрегация SUM(...) OVER(...) и AVG(...) OVER(...) для всех платежей по филиалу, как определено спецификатором окна OVER(,,,).

Ваша проблема в том, что ваши оконные функции агрегации пытаются получить доступ к необработанным данным, хотя я считаю, что вы собираетесь суммировать и усреднять сгруппированные значения. Вместо AVG(SalesTotal) OVER(...), я думаю, вам нужен AVG(SUM(SalesTotal)) OVER(...). Однако для случаев SUM() в расчете SalesResult я считаю, что вам нужна только простая (не оконная) ветвь и сумма платежа SUM(SalesTotal), а не сумма сумм на уровне ветки.

Кроме того, если вы ограничили FactSalesTable.SalesTotal > 0, строки FactSalesTable должны присутствовать, а ваш LEFT JOIN фактически является INNER JOIN.

Следующее должно быть ближе к тому, чего вы пытаетесь достичь.

SELECT 
    FactSalesTable.Date,
    FactSalesTable.PaymentID,
    Branch.* ,
    SUM(FactSalesTable.SalesTotal) AS TotalSales,
    AVG (SUM(FactSalesTable.SalesTotal)) OVER(PARTITION BY Branch.BCode) as AvgSales ,
    case 
        when SUM(FactSalesTable.SalesTotal)
             / AVG(SUM(FactSalesTable.SalesTotal)) OVER(PARTITION BY Branch.BCode) > 1
             THEN 'Above Avg' 
        when SUM(FactSalesTable.SalesTotal)
             / AVG(SUM(FactSalesTable.SalesTotal)) OVER(PARTITION BY Branch.BCode) = 1
            THEN 'Avg'
        else 'Below Avg'
    end as SalesResult
FROM Branch
LEFT JOIN FactSalesTable  ON Branch.BCode = FactSalesTable.BCode
WHERE FactSalesTable.SalesTotal > 0 and Branch.BCode = 1021
Group BY FactSalesTable.Date,Branch.BranchName ,Branch.BCode,FactSalesTable.PaymentID
ORDER BY FactSalesTable.Date DESC

Результаты:

Дата Идентификатор платежа БКод Имя ветки Всего продаж Средние продажи Результат продаж 30 апреля 2022 г. 57517 1021 Главный филиал 19939.00 16223.000000 Выше среднего 30 апреля 2022 г. 57519 1021 Главный филиал 12507.00 16223.000000 Ниже среднего

См. эту db<>fiddle. (Спасибо Барту МакЭндри за настройку тестовых данных.)

Вероятно, существуют способы дальнейшей реструктуризации запроса, чтобы ограничить избыточные выражения и улучшить читаемость, например, переместить исходную логику группировки в подзапрос или CTE и выполнить оконные операции в конечном/внешнем запросе. Другой вариант — обернуть всю логику платежей в CROSS APPLY.

Это сработало, но я искал группу по дате и сумме всех способов оплаты «общий ежедневный объем продаж», чтобы сравнить ее со средним значением, поэтому я удалил PaymantID. Спасибо

Ahmed 30.08.2024 19:45

@Ахмед, мне показалось, что группировка по PaymentID кажется подозрительной. Рад, что ты это понял. Еще одна мысль: если FactSalesTable.Date — это столбец даты/времени, но вы хотите группировать только по дате, возможно, вам придется использовать приведение или преобразование, например CONVERT(DATE, FactSalesTable.Date), как в группировке, так и в списке выбора и в порядке сортировки.

T N 30.08.2024 19:59

Другие вопросы по теме