#sql #subquery #case #aggregate
#sql #подзапрос #case #агрегировать
Вопрос:
Я новичок в stack overflow и самостоятельно изучал SQL для создания пользовательских отчетов на работе. Я был бы очень признателен, если бы кто-нибудь мог указать мне правильное направление, чтобы возвращать среднее значение при использовании выражения case, вот история:
Я пытаюсь создать запрос, который возвращает данные о ценах из счетов-фактур продаж. У меня есть функциональный отчет, но я пытаюсь стандартизировать ценовую единицу измерения, поскольку наши затраты не всегда устанавливаются в том же UOM, что и цена продажи. Я ограничен в том, какой код я могу написать, поскольку я использую внутреннюю программу создания отчетов, которая позволяет нам писать только подзапросы; У меня нет прямого доступа к СУБД.
Я написал оператор case в своем подзапросе, который решает проблему UOM, но я застрял, пытаясь агрегировать результаты.
После изменения [View_QB_SalesOrderLine].[Цена] в среднее значение ([View_QB_SalesOrderLine].[Цена], я попытался агрегировать выражение Case моего подзапроса, используя AVG как до, так и внутри оператора Case, но все, что я пытаюсь, приводит к сбою запроса.
Единственный код, который я написал ниже, — это подзапрос, все остальное генерируется инструментом создания отчетов. Я очень ценю любую помощь, которую я могу получить!
Обновлено запросом, который вызвал ошибку, а не рабочим кодом, который я пытался создать…урок усвоен. Этот запрос выполняется, если я удаляю AVG из обращения, но возвращает только средние значения [Цены], сгруппированные по MFR, КАТАЛОГУ и [условной стоимости СПА]. Для каждого экземпляра элемента создается новая строка с уникальным [условным значением стоимости СПА]. При использовании AVG перед выражением Case запрос выдает ошибки (ошибка: ссылка на объект не установлена для экземпляра объекта.) * Это сообщение кажется общим, поскольку это единственное сообщение, которое я когда-либо видел отображаемым, независимо от проблемы с запросом. Пожалуйста, имейте в виду, что я могу писать подзапросы только в этом инструменте, весь остальной код генерируется инструментом. Я подозреваю, что инструмент, автоматически добавляющий подзапрос в Group By, имеет какое-то отношение к ошибке при добавлении AVG в подзапрос.
Для контекста я добавил изображение того, как выглядит графический интерфейс, с которым я работаю. Я пишу пользовательские выражения в Notepad и вставляю их в инструмент.Report Writer
SELECT DISTINCT [Mfr] = [View_QB_SalesOrderLine].[Mfr]
,[CatalogNo] = [View_QB_SalesOrderLine].[CatalogNo]
,[SPA Cost Conv] = (AVG(CASE
WHEN [Price UOM] = [SPA Cost UOM]
THEN [SPA Cost]
WHEN [Price UOM] = 'E' AND [SPA Cost UOM] = 'C'
THEN [SPA Cost]/100
WHEN [Price UOM] = 'E' AND [SPA Cost UOM] = 'M'
THEN [SPA Cost]/1000
WHEN [Price UOM] = 'C' AND [SPA Cost UOM] = 'E'
THEN [SPA Cost] * 100
WHEN [Price UOM] = 'C' AND [SPA Cost UOM] = 'M'
THEN [SPA Cost] / 100
WHEN [Price UOM] = 'M' AND [SPA Cost UOM] = 'E'
THEN [SPA Cost] * 1000
WHEN [Price UOM] = 'M' AND [SPA Cost UOM] = 'C'
THEN [SPA Cost] * 100
END))
,[Price] = AVG([View_QB_SalesOrderLine].[Price])
,[Price UOM] = [View_QB_SalesOrderLine].[Price UOM]
FROM View_QB_SalesOrderLine
GROUP BY [View_QB_SalesOrderLine].[Mfr]
,[View_QB_SalesOrderLine].[CatalogNo]
,AVG(CASE
WHEN [Price UOM] = [SPA Cost UOM]
THEN [SPA Cost]
WHEN [Price UOM] = 'E' AND [SPA Cost UOM] = 'C'
THEN [SPA Cost]/100
WHEN [Price UOM] = 'E' AND [SPA Cost UOM] = 'M'
THEN [SPA Cost]/1000
WHEN [Price UOM] = 'C' AND [SPA Cost UOM] = 'E'
THEN [SPA Cost] * 100
WHEN [Price UOM] = 'C' AND [SPA Cost UOM] = 'M'
THEN [SPA Cost] / 100
WHEN [Price UOM] = 'M' AND [SPA Cost UOM] = 'E'
THEN [SPA Cost] * 1000
WHEN [Price UOM] = 'M' AND [SPA Cost UOM] = 'C'
THEN [SPA Cost] * 100
END)
,[View_QB_SalesOrderLine].[Price UOM]
ORDER BY [View_QB_SalesOrderLine].[Mfr] ASC
,[View_QB_SalesOrderLine].[CatalogNo] ASC
Комментарии:
1. Имея только одну таблицу, вам на самом деле не нужно уточнять ссылки на столбцы. Вам все равно следует проверить использование псевдонимов, которые облегчат чтение. Я думаю, что ваша проблема была бы решена с помощью
group by
, хотя.2. @shawnt00 Спасибо за совет по очистке ссылок на столбцы. Обычно я копирую и вставляю из инструмента, поскольку у меня нет IntelliSense для предотвращения опечаток, но вы правы, это определенно улучшает читаемость. Я не думаю, что могу использовать псевдонимы, поскольку я не могу редактировать код во внешнем запросе, если только они не были необходимы в подзапросе для объединений или аналогичных. Я только что отредактировал сообщение, чтобы прояснить проблему. Хотите знать, есть ли у вас какие-либо дополнительные сведения? Еще раз спасибо!
3. И что это за таинственные ошибки, которые вы получаете? Пожалуйста, отправьте сообщение в основной части вопроса.
4. Вы не должны запускать агрегированные запросы в
GROUP BY
предложении.5. @Parfait Я добавил ошибку в тело. Агрегат в
GROUP BY
предложении является проблемой. Как только я говорю составителю отчета усреднить цену, он добавляет все столбцы вGROUP BY
, я не могу это контролировать. Мне интересно, есть ли какая-то работа, где я могу агрегировать подзапросы без использования group by во внешнем запросе.
Ответ №1:
Вы ссылались на подзапросы и внешние запросы, но, похоже, ничто из приведенного выше не относится ни к одному из них. Это заставляет меня задуматься, нужно ли добавлять условие корреляции. Также обратите внимание, что Price
агрегат не был автоматически добавлен в столбцы группировки. Поэтому я не уверен, что мне интересно, являются ли причиной этого дополнительные круглые скобки или какой-либо неподдерживаемый синтаксис.
SELECT View_QB_SalesOrderLine.Mfr, View_QB_SalesOrderLine.CatalogNo,
AVG("SPA Cost UOM" *
CASE "Price UOM" "SPA Cost UOM"
WHEN 'EM' THEN 0.001
WHEN 'EC' THEN 0.01
WHEN 'CM' THEN 0.01
WHEN 'CE' THEN 100
WHEN 'MC' THEN 100
WHEN 'ME' THEN 1000
ELSE 1
EN) AS "SPA Cost Conv",
AVG(Price) AS Price
/* , "Price UOM" -- this is not valid here */
FROM View_QB_SalesOrderLine
GROUP BY Mfr, CatalogNo
ORDER BY Mfr, CatalogNo
Давным-давно я работал с инструментом запроса, который реорганизовывал разрывы строк, поэтому при использовании комментариев было безопаснее использовать форму в квадратных скобках /* */
, а не в конце строки --
. Возможно, вы захотите полностью удалить мою прокомментированную строку.
Комментарии:
1. Интересно, что оно не добавляет
PRICE
кGROUP BY
, я этого не заметил. Мне нравится логика, которую вы использовали для преобразования, я собираюсь подключить это. Является ли это более эффективным таким образом? Я не могу просто подключить запрос, который вы написали, из-за того, как работает инструмент. Я могу добавить только выражение, которое вернет один столбец, кажется, что когда я пишу выражение, оно обрабатывается как подзапрос (именно здесь вокругCASE
выражения появляются дополнительные круглые скобки. Чтобы продемонстрировать, вот что происходит, когда я создаю пустой запрос и добавляю одно выражение: (слишком длинное, я опубликую в следующем комментарии.)2.
SELECT [Expr 1] = (SELECT * FROM [View_QB_SalesOrderLine]) FROM
Я только написалSELECT * FROM [View_QB_SalesOrderLine]
, остальное было сгенерировано системой.3. Пожалуйста, взгляните на изображение автора отчета в исходном сообщении, если вы хотите увидеть, как выглядит графический интерфейс. Может помочь с тем, что я изо всех сил пытаюсь объяснить.
4. @Ryan Отсутствие эффективности здесь не вызывает беспокойства. Что, если вы просто используете одно только выражение обращения, а затем попросите составителя отчета агрегировать его, как вы сделали со столбцом цены?
5. БОЖЕ … клянусь, я уже пробовал это, и раньше это не удавалось, но я просто попробовал это снова, и это работает! Так просто! Должно быть, у меня была какая-то синтаксическая ошибка, когда я пробовал раньше. Устранение неполадок в этом инструменте может быть очень сложным! Большое спасибо за то, что помогли мне добраться туда!
Ответ №2:
использовать
Group BY
в вашем коде, основанном на требовании, которое, как я полагаю, в вашем случае было бы продано
Комментарии:
1. Спасибо за предложение. Я только что обновил сообщение, фактически показывающее запрос с использованием group by, который продолжает вызывать ошибки. Интересно, есть ли у вас какие-либо мысли?