SQL-запрос для отображения пользователей с нулевыми значениями - PullRequest
0 голосов
/ 19 июня 2019

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

SELECT
    SUM(CASE WHEN TimeTransactions.ChargeBasis = 'C' THEN TimeTransactions.QuantityOfTime/60/6 ELSE 0 END) AS ChargableUnits,
    SUM(CASE WHEN TimeTransactions.ChargeBasis = 'N' THEN TimeTransactions.QuantityOfTime/60/6 ELSE 0 END) AS NonChargableUnits,
    SUM(CASE WHEN TimeTransactions.ChargeBasis = 'C' THEN TimeTransactions.ValueOfTime ELSE 0 END) AS ChargableValue,   
    SUM(CASE WHEN TimeTransactions.ChargeBasis = 'N' THEN TimeTransactions.ValueOfTime ELSE 0 END) AS NonChargableValue,
    SUM(TimeTransactions.QuantityOfTime)/60/6 AS TotalUnits,
    SUM(TimeTransactions.ValueOfTime) AS TotalValue,
    Users.Code AS FeeEarner
FROM
    Users INNER JOIN TimeTransactions ON TimeTransactions.FeeEarnerRef = Users.Code
WHERE
Users.FeeEarner = 1 AND Users.UserStatus = 0 AND
 TimeTransactions.TransactionDate >= dateadd(day,datediff(day,1,GETDATE()),0)
 AND TimeTransactions.TransactionDate < dateadd(day,datediff(day,0,GETDATE()),0)
GROUP BY
    Users.Code

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

Любая помощь или руководство будет принята с благодарностью:)

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Вы должны использовать LEFT JOIN.Но очень важно правильно определить условия фильтрации:

SELECT SUM(CASE WHEN tt.ChargeBasis = 'C' THEN tt.QuantityOfTime/60/6 ELSE 0 END) AS ChargableUnits,
       SUM(CASE WHEN tt.ChargeBasis = 'N' THEN tt.QuantityOfTime/60/6 ELSE 0 END) AS NonChargableUnits,
       SUM(CASE WHEN tt.ChargeBasis = 'C' THEN tt.ValueOfTime ELSE 0 END) AS ChargableValue,   
       SUM(CASE WHEN tt.ChargeBasis = 'N' THEN tt.ValueOfTime ELSE 0 END) AS NonChargableValue,
       SUM(tt.QuantityOfTime)/60/6 AS TotalUnits,
       SUM(tt.ValueOfTime) AS TotalValue,
       u.Code AS FeeEarner
FROM Users u LEFT JOIN
     TimeTransactions tt
     ON tt.FeeEarnerRef = u.Code AND
        tt.TransactionDate >= dateadd(day, -1, CONVERT(date, GETDATE())) AND
        tt.TransactionDate < CONVERT(date, GETDATE())
WHERE u.FeeEarner = 1 AND u.UserStatus = 0 
GROUP BY u.Code;

Примечания:

  • Условия TimeTransactions должны идти в предложении ON, а не вWHERE.
  • SQL Server поддерживает тип данных DATE.Для удаления компонента времени из значения не требуется выполнять тайные вычисления с использованием разностей дат.
  • Псевдонимы таблиц облегчают написание и чтение запроса.
1 голос
/ 19 июня 2019

Что-то вроде этого сделает это.

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

EDIT:

Это рабочий пример того, чего вы пытаетесь достичь. Я значительно упростил структуру таблицы, поскольку столбцы, указанные в запросе, не соответствуют столбцам, указанным в примерах изображений. Также похоже, что запрос пытается использовать псевдоним столбца в предложении where (что невозможно в SQL-сервере).

В приведенном ниже примере я применил фильтрацию к таблице временных транзакций в общем выражении таблицы, а затем оставил присоединенную к ней пользовательскую таблицу. Это приводит к следующему выводу.

enter image description here

Вы видите, что для пользователей, чьи временные транзакции не соответствуют условию фильтрации, возвращается ноль, тогда как при использовании внутреннего объединения эти пользователи вообще не возвращаются.

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

Удачи, если у вас есть какие-либо вопросы, дайте мне знать.

declare @users table (
    userid int identity(1,1),
    username nvarchar(50)
);

declare @timetransaction table (
    timetransactionid int identity(1,1),
    userid int,
    quantityoftime int
);

insert @users
values
('SomeBody'),
('AnyBody'),
('SomeoneElse');

insert @timetransaction
values
(1, 7),
(1, 12),
(2, 5),
(3, 71),
(3, 4);

declare @userid int = 1;

with timetransaction as (select userid, quantityoftime from @timetransaction where userid=1)

select u.userid, coalesce(SUM(quantityoftime), 0) as total from @users u
left join timetransaction t on u.userid=t.userid
group by u.userid;

Пример таблицы пользователей введите описание изображения здесь

Пример таблицы временных транзакций
введите описание изображения здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...