sql联接未从另一个表获取所有记录

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了sql联接未从另一个表获取所有记录相关的知识,希望对你有一定的参考价值。

我有这样的查询

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名员工。但是,这里只显示了一些受到打孔的员工。我想向员工主管显示所有员工

答案

我相信问题在于他的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连接,以使该语句更具可读性。

另一答案

如果要将所有内容保留在特定表中,则该表应该是FROM子句中的第一个表。后续联接应为LEFT JOIN,后续表中的条件应位于ON子句中,而不是WHERE子句中。

[我也建议您使用表别名,并且仅对字符串和日期常量使用单引号-而不是列别名。

以下内容假设IOTypeEdatetime在表Mx_ACSEventTrn中。我不应该猜测。您应该在查询中限定all列名。

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的原因。

以上是关于sql联接未从另一个表获取所有记录的主要内容,如果未能解决你的问题,请参考以下文章

TableView 未从另一个 tableview 中的 didselectRowAtindexPath 加载

Access SQL 中的联接语句

SQL小知识_长期总结

根据案例条件应用联接的 SQL 查询

仅从另一个联接表中选择第一行

如何使用消除重复的联接从另一个表中插入一个表[重复]