如何在sql中使用union?

时间:2013-12-14 16:22:33

标签: sql join union

我在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行超时。

3 个答案:

答案 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 

如果您需要处理在某一天多次登记,或者在午夜之前办理登机手续以及在午夜之后结帐等等的人,您可能需要使加入条件更加复杂。但是对于简单的白班一次一旦出现问题,这将有效。