我在sql数据库[dbo]中有一个表。[ClockInClockOut]有3列:[UserId],ClockInClockOutTypeId],[CreatedDate]。我需要显示像
这样的数据UserName CreatedDate TimeIn TimeOut
abc 12/31/2013 13:19:51 13:22:37
xyz 1/31/2013 14:19:51 15:19:51
我在sql中执行此操作:
select u.[UserName],
CONVERT(VARCHAR(20), c.[CreatedDate], 101) as [Date],
CASE WHEN c.[ClockInClockOutTypeId]=1 and THEN CONVERT(VARCHAR(20), c.[CreatedDate], 108) ELSE null END as InTime,
CASE WHEN c.[ClockInClockOutTypeId]=2 THEN CONVERT(VARCHAR(20), c.[CreatedDate], 108) ELSE null END as OutTime
from [ClockInClockOut] as c
inner join [UserProfile] as u on c.UserId = u.[UserId]
我得到了这个结果:
UserName CreatedDate TimeIn TimeOut
abc 12/31/2013 13:19:51 null
abc 12/31/2013 null 14:19:51
在第1行第3栏时间是好的,但我需要在第4列而不是第4列的第2行超时。
答案 0 :(得分:2)
您需要第二次加入ClockInClockOut
,而不是union the results。
我会做类似
的事情SELECT
u.UserName,
CONVERT(VARCHAR(20), c1.[CreatedDate], 101) as [Date],
CONVERT(VARCHAR(20), c1.[CreatedDate], 108) as InTime,
CONVERT(VARCHAR(20), c2.[CreatedDate], 108) as OutTime
FROM [ClockInClockOut] as c1
INNER JOIN [ClockInClockOut] as c2 ON c1.UserId = c2.UserId
-- getting the specific date is a little tricky, unquestionably better ways exist
AND CONVERT(VARCHAR(20), c1.[CreatedDate], 101) = CONVERT(VARCHAR(20), c2.[CreatedDate], 101)
INNER JOIN [UserProfile] as u on c1.UserId = u.[UserId]
WHERE
c1.ClockInClockOutTypeId = 1 AND c2.ClockInClockOutTypeId = 2
或者,如果您不喜欢,可以汇总初始查询...
SELECT
a.UserName, a.Date
MAX(a.InTime) As InTime,
MAX(a.OutTime) As OutTime
FROM (
SELECT
u.[UserName],
CONVERT(VARCHAR(20), c.[CreatedDate], 101) as [Date],
CASE WHEN c.[ClockInClockOutTypeId]=1 and THEN CONVERT(VARCHAR(20), c.[CreatedDate], 108) ELSE null END as InTime,
CASE WHEN c.[ClockInClockOutTypeId]=2 THEN CONVERT(VARCHAR(20), c.[CreatedDate], 108) ELSE null END as OutTime
FROM[ClockInClockOut] as c
INNER JOIN [UserProfile] as u on c.UserId = u.[UserId]
) a
GROUP BY a.UserName, a.Date
答案 1 :(得分:1)
测试数据
DECLARE @ClockInClockOut TABLE
([UserId] INT, [ClockInClockOutTypeId] SMALLINT, [CreatedDate] DATETIME)
INSERT INTO @ClockInClockOut
VALUES
(1,1,'2013-12-10 09:42:08.603'),
(1,2,'2013-12-10 16:42:08.603'),
(1,1,'2013-12-11 16:42:08.603'),
(1,2,'2013-12-11 18:42:08.603'),
(2,1,'2013-12-12 09:42:08.603'),
(2,2,'2013-12-12 16:42:08.603'),
(2,1,'2013-12-13 11:42:08.603'),
(2,2,'2013-12-13 15:42:08.603')
DECLARE @UserProfile TABLE (USERID INT, USERNAME VARCHAR(20))
INSERT INTO @UserProfile
VALUES (1, 'Mark'),
(2, 'John')
<强>查询强>
;With TimeI
AS
(
SELECT UserID, [CreatedDate],
CONVERT(VARCHAR(20), [CreatedDate], 108) AS InTime
FROM @ClockInClockOut
WHERE [ClockInClockOutTypeId]=1
),
TimeO
AS
(
SELECT UserID,[CreatedDate],
CONVERT(VARCHAR(20), [CreatedDate], 108) AS OutTime
FROM @ClockInClockOut
WHERE [ClockInClockOutTypeId]=2
)
SELECT DISTINCT USERNAME , CAST(CO.[CreatedDate] AS DATE) AS [CreatedDate], TI.Intime, T.OutTime
FROM @UserProfile UP INNER JOIN @ClockInClockOut CO
ON UP.USERID = CO.UserId
INNER JOIN TimeI TI
ON UP.USERID = ti.UserId
AND CAST(CO.[CreatedDate] AS DATE) = CAST(TI.[CreatedDate] AS DATE)
INNER JOIN TimeO T
ON UP.USERID = t.UserId
AND CAST(CO.[CreatedDate] AS DATE) = CAST(T.[CreatedDate] AS DATE)
结果集
USERNAME CreatedDate Intime OutTime
John 2013-12-12 09:42:08 16:42:08
John 2013-12-13 11:42:08 15:42:08
Mark 2013-12-10 09:42:08 16:42:08
Mark 2013-12-11 16:42:08 18:42:08
答案 2 :(得分:1)
在ClockInClockOut
表上使用自联接可能比尝试使用UNION更容易。
SELECT u.UserName, i.Date, i.InTime, o.OutTime
FROM (SELECT u.UserName,
CONVERT(VARCHAR(20), c.CreatedDate, 101) AS Date,
CONVERT(VARCHAR(20), c.CreatedDate, 108) AS InTime
FROM ClockInClockOut AS c
WHERE c.ClockInClockOutTypeId = 1) AS i
JOIN (SELECT u.UserName,
CONVERT(VARCHAR(20), c.CreatedDate, 101) AS Date,
CONVERT(VARCHAR(20), c.CreatedDate, 108) AS InTime
FROM ClockInClockOut AS c
WHERE c.ClockInClockOutTypeId = 2) AS o
ON i.UserName = o.UserName AND i.Date = o.Date
JOIN UserProfile AS u ON i.UserId = u.UserId
如果您需要处理在某一天多次登记,或者在午夜之前办理登机手续以及在午夜之后结帐等等的人,您可能需要使加入条件更加复杂。但是对于简单的白班一次一旦出现问题,这将有效。