【问题标题】:How to use union in sql?如何在sql中使用union?
【发布时间】:2013-12-14 16:22:33
【问题描述】:

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

【问题讨论】:

  • 您有一个名为ClockInClockOut,位于一个身份不明的数据库中(名称无关紧要)。让你的术语直截了当;如果您将表称为数据库,您将混淆您自己和您尝试寻求帮助的每个人。

标签: sql join union


【解决方案1】:

您需要在第二次加入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

【讨论】:

    【解决方案2】:

    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 
    

    如果您需要处理在某一天多次签到的人,或者在午夜之前签到并在午夜之后结帐的人等,您可能需要使联接条件更加复杂。但是对于简单的白班一次in,一旦出局,这将起作用。

    【讨论】:

      【解决方案3】:

      测试数据

      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
      

      【讨论】:

        猜你喜欢
        • 2011-06-10
        • 2010-12-08
        • 1970-01-01
        • 2021-08-21
        • 1970-01-01
        • 2011-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多