sql join не берет все записи из другой таблицы - PullRequest
0 голосов
/ 03 ноября 2019

У меня есть такой запрос

WITH CTE AS 
(
    SELECT
        U.Name, U.Adluserid AS 'Empid', 
        MIN(CASE WHEN IOType = 0 THEN Edatetime END) AS 'IN',
        MAX(CASE WHEN IOType = 1 THEN Edatetime END) AS 'out',
        (CASE  
            WHEN MAX(E.Status) = 1 THEN 'AL' 
            WHEN MAX(E.Status) = 2 THEN 'SL' 
            ELSE 'L' 
         END) AS leave_status
    FROM
        Mx_ACSEventTrn
    RIGHT JOIN
        Mx_UserMst U ON Mx_ACSEventTrn.UsrRefcode = U.UserID
    LEFT JOIN
        Tbl_Zeo_Empstatus E ON Mx_ACSEventTrn.UsrRefcode = E.Emp_Id
    WHERE
        CAST(Edatetime AS DATE) BETWEEN '2019-11-03' AND '2019-11-03' 
    GROUP BY
        U.Name, U.Adluserid
)
SELECT 
    [Name], [Empid], [IN], [OUT],
    (CASE 
        WHEN CAST([IN] AS TIME) IS NULL THEN CAST(leave_status AS NVARCHAR(50))
        WHEN CAST([IN] AS TIME) < CAST('08:15' AS TIME) THEN 'P' 
        ELSE 'L' 
     END) AS status
FROM 
    CTE

В основной таблице моего сотрудника Mx_UserMst У меня 67 сотрудников. Но здесь это показывает лишь несколько сотрудников, тех, кто ударил кулаком. Я хочу показать всех сотрудников из master master

Ответы [ 2 ]

0 голосов
/ 03 ноября 2019

Если вы хотите сохранить все в определенной таблице, то это должна быть первая таблица в предложении FROM. Последующие объединения должны быть LEFT JOIN с, а условия для последующих таблиц должны быть в предложении ON, а не в предложении WHERE.

Я бы также посоветовал вам использовать псевдонимы таблиц и использовать только одинарные кавычки. для констант строки и даты - НЕ псевдонимы столбцов.

Следующее предполагает, что IOType и Edatetime находятся в таблице Mx_ACSEventTrn. Я не должен был догадываться. Вы должны указать все имена столбцов в запросе.

WITH CTE AS (
      SELECT U.Name, U.Adluserid AS Empid, 
             MIN(CASE WHEN AE.IOType = 0 THEN AE.Edatetime END) AS in_dt,
             MAX(CASE WHEN AE.IOType = 1 THEN AE.Edatetime END) AS out_dt,
             (CASE WHEN MAX(ES.Status) = 1 THEN 'AL' 
                   WHEN MAX(ES.Status) = 2 THEN 'SL' 
                   ELSE 'L' 
              END) AS leave_status
      FROM Mx_UserMst U LEFT JOIN
           Mx_ACSEventTrn AE
           ON AE.UsrRefcode = U.UserID AND
              CAST(AE.Edatetime AS DATE) BETWEEN '2019-11-03' AND '2019-11-03' LEFT JOIN
           Tbl_Zeo_Empstatus ES 
           ON AE.UsrRefcode = ES.Emp_Id AND               
      GROUP BY U.Name, U.Adluserid
     )
SELECT Name, Empid, IN_DT, OUT_DT,
       (CASE WHEN IN_DT IS NULL THEN leave_status
             WHEN CAST(IN_DT AS TIME) < CAST('08:15' AS TIME) THEN 'P' 
             ELSE 'L' 
        END) AS status
FROM CTE;

Еще несколько пунктов:

  • Не называйте псевдонимами такие вещи, как IN, которые являютсяуже ключевые слова. Вот почему я дал ему имя IN_DT.
  • Нет смысла приводить к TIME для сравнения с NULL.
  • Я не вижу причин дляприведен к NVARCHAR(50) во внешнем CASE выражении.
0 голосов
/ 03 ноября 2019

Я считаю, что проблема в его WHERE предложении:

where cast(Edatetime as date) between '2019-11-03' and '2019-11-03'

Почему бы не cast(Edatetime as date) = '2019-11-03'? Я не уверен, к какой таблице принадлежит столбец Edatetime (необходимо указать все столбцы с правильным именем / псевдонимом таблицы). Вы должны переместить условие в предложение ON:

WITH CTE AS 
(
  select U.Name,U.Adluserid as 'Empid', 
       min(case when IOType=0 then Edatetime end) as 'IN',
       max(case when IOType=1 then Edatetime end) as 'out',
       case max(E.Status) when 1 then 'AL' when 2 then 'SL' else 'L' end as leave_status
  from Mx_UserMst U
  left join Mx_ACSEventTrn on Mx_ACSEventTrn.UsrRefcode=U.UserID and (cast(Edatetime as date) between '2019-11-03' and '2019-11-03')
  left join Tbl_Zeo_Empstatus E on Mx_ACSEventTrn.UsrRefcode=E.Emp_Id 
  group by U.Name,U.Adluserid
)
SELECT [Name], [Empid],[IN],[OUT],
  case 
    when cast([IN] as time) is null then cast(leave_status as nvarchar(50))
    when cast([IN] as time) < cast('08:15' as time) then 'P' 
    else 'L' 
  end as status
FROM CTE

Если Edatetime принадлежит Tbl_Zeo_Empstatus, переместите условие в предложение ON следующего соединения. Я также изменил RIGHT на LEFT соединение, чтобы сделать оператор более читабельным.

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