需要基于另一张桌子的所有进出时间?

Posted

技术标签:

【中文标题】需要基于另一张桌子的所有进出时间?【英文标题】:Need all in and out time based on another table? 【发布时间】:2018-10-29 07:57:24 【问题描述】:

我有两张表,根据表 1 的进出时间,我尝试在表 2 中获取所有进出时间。下面的查询适用于白天工作的拳头,但夜间输出会有所不同。

表 1:Daily_attendace_data

att_date    emp_code      in_time                   out_time
2018-10-21  9999    2018-10-21 08:00:00.000 2018-10-22 06:00:00.000

表 2:Trnevents

emp_reader_id          DT
9999                2018-10-21 08:00:00.000
9999                2018-10-22 06:00:00.000

我的查询:

我正在使用枢轴来获得所有拳头

declare @tempProcesstable as table(
    [id] [nvarchar](200) NULL,
    [time_stamp] datetime NULL,
    [AccessType] varchar(3)  NULL) 
insert into @tempProcesstable 

        select distinct t1.emp_Reader_id, t1.DT,t1.eventid from   daily_attendance_data t2 join trnevents t1
on t1.emp_reader_id=t2.emp_reader_id where   (CONVERT(VARCHAR(26), t2.att_Date, 23) >=CONVERT(VARCHAR(26), '2018-10-20', 23) 
                       and CONVERT(VARCHAR(26), t2.att_date, 23) <=CONVERT(VARCHAR(26), '2018-10-21', 23))
                   and
                   (t1.DT >=t2.in_time 
                       and  t1.DT <=t2.out_time)
                        --   and t1.emp_reader_id=1000
                               group by t1.emp_Reader_id,t1.dt,t1.eventid order by t1.emp_reader_id,DT asc
                  ; With CheckIns
As (Select Rowemp_reader_id = Row_Number() Over (Partition by id, Cast(time_stamp As Date) Order By time_stamp),
        id, time_stamp,
        [Date] = Cast(time_stamp As Date),

        [Time] = Cast(time_stamp As Time(0))
    From @tempProcesstable)
Select Pvt.id,B.emp_name ,  [Date], CHECK1, CHECK2,Cast(dateadd(ss,datediff(ss,CHECK1,CHECK2),0) As Time(0)) Total1,
 CHECK3, CHECK4,Cast(dateadd(ss,datediff(ss,CHECK3,CHECK4),0) As Time(0)) Total2


From (Select id, [Date], [Time],
        CHECKNum = 'CHECK' + Cast(Rowemp_reader_id As varchar(11))
    From CheckIns) As P
Pivot (Min([Time])
    For CheckNum In (Check1, [Check2], Check3, Check4)
    ) As Pvt    

     LEFT OUTER JOIN
                      dbo.employee AS B ON Pvt.id= B.emp_reader_id LEFT OUTER JOIN
                      dbo.departments AS C ON B.dept_id = C.dept_id 

我的输出:

id  emp_name    Date         CHECK1   CHECK2    Total1  CHECK3  CHECK4  Total2
9999    Test    2018-10-21  08:00:00    NULL    NULL    NULL    NULL    NULL
9999    Test    2018-10-22  06:00:00    NULL    NULL    NULL    NULL    NULL

我的预期输出:

id       att_date     Check1    Check2    Check3    Check4
9999    2018-10-21  08:00:00    06:00:00    NULL    NULL

如果我只按 id 进行分区,它会得到我预期的输出,但不适用于所有天。我卡在这里,任何人都可以帮助解决这个问题。

【问题讨论】:

1- 您需要更具体地了解您的 sql server 版本,因为在 2012 年他们引入了 LAG 和 LEAD 和 man,这些功能很有用。 2- 我记得类似的问题,并回答了very similar one using CTE's。它可能是重复的/已经回答了。 Getting all punch in and punch out of an employee?的可能重复 s 但我正在尝试连续进出所有内容 这就是我在第一条评论中的回答。它将输入/输出表数据转换为具有两列(输入和输出)的一行。你可以检查一下,试试看,如果你觉得有用,就点个赞吧。 D-shih 给出的答案是您所需要的,使用 CTE 来获得有序的拳头并从中工作(他所做的分组和条件总和非常适合您的用例) 【参考方案1】:

您可以尝试通过att_date日期在子查询中制作行号,然后使用条件聚合函数来制作。

SELECT emp_readr_id,
       emp_name,
       att_date,
       MAX(CASE WHEN RN = 1 THEN time END) 'CHECK1',
       MAX(CASE WHEN RN = 2 THEN time END) 'CHECK2',
       MAX(CASE WHEN RN = 3 THEN time END) 'CHECK3',
       MAX(CASE WHEN RN = 4 THEN time END) 'CHECK4'
FROM (
   SELECT emp_readr_id,
       emp_name,
       att_date ,
       ROW_NUMBER() OVER(PARTITION BY att_date ORDER BY DT) rn,
        CONVERT(VARCHAR(10),DT,108) time
FROM Daily d 
JOIN Trnevents t on t.DT between d.in_time and d.out_time
) t1
group by emp_readr_id,
       emp_name,
       att_date

sqlfiddle

结果

id       att_date     Check1    Check2    Check3    Check4
9999    2018-10-21  08:00:00    06:00:00    NULL    NULL

【讨论】:

关于特定Trnevents 表的第二个问题,很高兴知道什么产品提供了该表(以及为什么不将数据存储在日期时间列中)。 ***.com/questions/48205873/…【参考方案2】:

试试这个查询。请注意,这里我创建了一个临时表作为#Base。

IF OBJECT_ID('tempdb.dbo.#Base', 'U') IS NOT NULL
    DROP TABLE #Base; 

CREATE table #Base
(
    emp_code INT, att_date DATE, DT DATETIME, ColName VARCHAR(MAX)
)

INSERT INTO #Base
SELECT X.emp_code, X.att_date, X.DT, 'Check'+CAST(X.Num AS VARCHAR(MAX))
FROM
(
  SELECT Row_Number() Over (Partition By D.emp_code, D.att_date  Order By D.emp_code, D.att_date ) As Num, *
  FROM Daily_attendace_data D
  INNER JOIN Trnevents T ON T.emp_reader_id = D.emp_code AND T.DT BETWEEN D.in_time 
  AND D.out_time
) X
ORDER BY X.DT


DECLARE @cols AS NVARCHAR(MAX),    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(ColName) 
                from #Base
                group by ColName, DT
                order by ColName
        FOR XML PATH(''), TYPE
        ).value('.', 'NVARCHAR(MAX)') 
    ,1,1,'')


set @query = N'SELECT emp_code, att_date, ' + @cols + N' from 
         (
            select DT, ColName, emp_code, att_date
            from #Base
        ) x
        pivot 
        (
            max(DT)
            for ColName in (' + @cols + N')
        ) p '


exec sp_executesql @query;

【讨论】:

感谢您提供宝贵的答案。我会尽力回复你 @TimeAttendanceSystem 我做了一个小的修改。请检查最新查询 我不喜欢这个答案,因为它过于复杂,CTE+group by 更容易维护(并且性能更好)。

以上是关于需要基于另一张桌子的所有进出时间?的主要内容,如果未能解决你的问题,请参考以下文章

我怎样才能将它从一张桌子存储到另一张桌子?

按另一张桌子的数量排序?

按另一张桌子的数量排序?

从另一张桌子算起来

用 Selenium 刮一张桌子并打印它

用sql 语句 怎么样查询一张表的所有内容 和 另一张表的部分内容? 求解