#sql #sql-server #group-by
#sql #sql-сервер #группировка по
Вопрос:
У меня следующие результаты:
Получено с помощью этого запроса:
SELECT b.name, ISNULL(SUM(amount),0) AS 'Total', ISNULL(AVG(amount),0) AS 'Average'
FROM User_Transaction a
RIGHT OUTER JOIN Category b ON (a.category_id = b.category_id)
GROUP BY b.name
Он содержит итоговые и средние значения всех финансовых транзакций, зарегистрированных пользователями, независимо от того, когда транзакция была зарегистрирована.
В User_Transaction
таблице есть datestamp
столбец, который я хотел бы отфильтровать. Итак, я пытаюсь выполнить следующее:
SELECT b.name, ISNULL(SUM(amount),0) AS 'Total', ISNULL(AVG(amount),0) AS 'Average'
FROM User_Transaction a
RIGHT OUTER JOIN Category b ON (a.category_id = b.category_id)
WHERE
a.datestamp BETWEEN @date_from AND @date_to
GROUP BY b.name
ORDER BY b.name
Это дает мне:
Записи Other
и Salary
отсутствуют, потому что никто никогда не совершал транзакцию с этими именами, и поэтому нет даты для фильтрации.
Тем не менее, я хотел бы включить эти имена, но все равно ноль для их значений. Как я могу это сделать?
Комментарии:
2. Пожалуйста, подскажите, что не так с вопросом, заслуживает ли он понижения. Раньше я не задавал много вопросов по SQL
3. Отрицательный результат не мой, но данные в виде изображения плохо воспринимаются с помощью вопросов SQL. Вам лучше опубликовать его как форматированный
text
или как инструкции DDL и DML.4. @Larnu Я понимаю. Спасибо за совет — я запомню его для следующего раза.
Ответ №1:
Хорошо, по сути, вы хотите перечислить ВСЕ категории и включить общее и среднее значение, если такие данные доступны за указанный период времени?
Если это ваше намерение, тогда читайте дальше!
Прежде всего я переформатировал запрос, чтобы было легче понять структуру. Я переименовал псевдоним таблицы для User_Tranaction с «a» на «ut», а псевдоним для категории с «b» на «cat»
SELECT
cat.name,
ISNULL(SUM(amount),0) AS 'Total',
ISNULL(AVG(amount),0) AS 'Average'
FROM
User_Transaction AS ut
RIGHT OUTER JOIN Category AS cat
ON ut.category_id = cat.category_id
WHERE
ut.datestamp BETWEEN @date_from AND @date_to
GROUP BY
cat.name
ORDER BY
cat.name
Чтобы добиться желаемого эффекта перечисления всех категорий и сопоставления только пользовательских транзакций за период времени, я перевернул объединение таблиц, чтобы использовать ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ из Category в User_Transaction . Кроме того, я перенес фильтрацию по дате в предложение ON соединения с User_Transaction . Это приводит к предварительной фильтрации данных в User_Transactions, прежде чем результирующие данные будут связаны с данными категории.
SELECT
cat.name,
ISNULL(SUM(amount),0) AS 'Total',
ISNULL(AVG(amount),0) AS 'Average'
FROM
Category AS cat
LEFT OUTER JOIN User_Transaction AS ut
ON cat.category_id = ut.category_id
AND ut.datestamp BETWEEN @date_from AND @date_to
GROUP BY
cat.name
ORDER BY
cat.name
Надеюсь, это поможет.
Ответ №2:
Попробуйте добавить OR a.datestamp IS NULL
условие where:
SELECT b.name, ISNULL(SUM(amount),0) AS 'Total', ISNULL(AVG(amount),0) AS 'Average'
FROM User_Transaction a
RIGHT OUTER JOIN Category b ON (a.category_id = b.category_id)
WHERE
a.datestamp BETWEEN @date_from AND @date_to OR a.datestamp IS NULL
GROUP BY b.name
ORDER BY b.name
Ответ №3:
Поехали
SELECT c.name, ISNULL(SUM(amount),0) AS 'Total', ISNULL(AVG(amount),0) AS 'Average'
FROM User_Transaction ut
RIGHT OUTER JOIN Category c ON (ut.category_id = c.category_id)
WHERE
(ut.datestamp BETWEEN @date_from AND @date_to) OR ut.datestamp IS NULL
GROUP BY c.name
ORDER BY c.name
Ответ №4:
Я думаю, что это сработает с ОБЪЕДИНЕНИЕМ: сначала поместите свой запрос, а во второй части ОБЪЕДИНЕНИЯ выберите записи, в которых нет дат для фильтрации. Это должно работать так
Комментарии:
1. Я вижу
UNION
, что это работает, но одной из проблем может быть эффективность. Я полагаю, что таблицы в запросах будут вызываться дважды.