Как фильтровать результаты в ГРУППЕ ПО запросу по столбцу, который не включен в результаты?

#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 отсутствуют, потому что никто никогда не совершал транзакцию с этими именами, и поэтому нет даты для фильтрации.

Тем не менее, я хотел бы включить эти имена, но все равно ноль для их значений. Как я могу это сделать?

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

1. Вредные привычки, от которых нужно отказаться: использование псевдонимов таблиц, таких как (a, b, c) или (t1, t2, t3)

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 , что это работает, но одной из проблем может быть эффективность. Я полагаю, что таблицы в запросах будут вызываться дважды.