2

従業員のログイン情報を格納するテーブルがあります

ログインテーブルのサンプルデータは

 EmpID  Status     [Time]
 100    SignIn    2013-03-07 11:41:44.473
 101    SignIn    2013-03-07 10:41:44.473
 100    SignOut   2013-03-07 12:41:44.473
 101    SignOut   2013-03-07 11:41:44.473
 101    SignIn    2013-03-08 11:41:44.473

私は結果が欲しい

EmpID   SignIn                    SignOut
 100    2013-03-07 11:41:44.473    2013-03-07 12:41:44.473
 101    2013-03-07 10:41:44.473    2013-03-07 11:41:44.473
 101    2013-03-08 11:41:44.473    NULL

PIVOTを使ってみた

Select EmpID,[SignIn],[SignOut]
from 
(Select EmpId,status,LoginTime from Login)p
 pivot
(
 min(Logintime)
 For status in ([SignIn],[SignOut])
)pvt

しかし、上記のクエリは、Time but valueEmployee 101を持つ最後の行を除外していますSignInno SignOut

テーブル データを生成するためのSQLFiddle

4

2 に答える 2

4

関数を使用して正しい軌道に乗っていました。に基づいて各行にを割り当てるPIVOT方法が必要でした。 / 次のコードを使用できます。row_number()empidstatusdatepivot

Select EmpID,[SignIn],[SignOut]
from 
(
  Select EmpId, status, 
    LoginTime, 
    cast(logintime as date) date,
    row_number() over(partition by empid, status, cast(logintime as date)
                      order by logintime) rn
  from Login
)p
pivot
(
  min(Logintime)
  For status in ([SignIn],[SignOut])
)pvt

SQL Fiddle with Demoを参照してください。

サブクエリに 2 つの新しい列があります。1 つはrow_number()各行の を生成し、2 番目dateは時間なしで を生成します。これらの列は両方とも で使用されGROUP BYますが、最終的な選択には表示されません。これらは、毎日 (必要な場合) 各従業員に対して複数の行を取得できるように使用されます。

SQLフィドルからの@IvanGのデータを使用した結果は次のとおりです。

| EMPID |              SIGNIN |             SIGNOUT |
-----------------------------------------------------
|   100 | 2013-03-07 11:41:44 | 2013-03-07 12:41:44 |
|   101 | 2013-03-07 10:41:44 | 2013-03-07 11:41:44 |
|   101 | 2013-03-08 11:41:44 |              (null) |
|   102 | 2013-04-08 12:41:44 | 2013-04-08 13:41:44 |
|   102 | 2013-04-08 16:41:44 | 2013-04-08 17:41:44 |
|   102 | 2013-04-08 19:41:44 |              (null) |
于 2013-03-07T11:02:03.313 に答える
3

次のように取得できます。

SELECT  l1.EmpID
        , l1.LoginTime [SignIn]
        , l2.LoginTime [SignOut]
FROM    Login l1
LEFT JOIN   
        Login l2 ON 
        l2.EmpID = l1.EmpID
AND     CAST(l2.LoginTime AS DATE) = CAST(l1.LoginTime AS DATE)
AND     l2.status = 'SignOut'
WHERE   l1.status = 'SignIn'

従業員に対して 1 日に複数のサインイン/サインアウトがあり、その日の最初SignInと最後を取得したいSignOut場合は、クエリを変更する必要があることに注意してください。

SELECT  l1.EmpID
        , MIN(l1.LoginTime) [SignIn]
        , MAX(l2.LoginTime) [SignOut]
FROM    Login l1
LEFT JOIN   
        Login l2 ON 
        l2.EmpID = l1.EmpID
AND     CAST(l2.LoginTime AS DATE) = CAST(l1.LoginTime AS DATE)
AND     l2.status = 'SignOut'
WHERE   l1.status = 'SignIn'
GROUP BY
        l1.EmpID, CAST(l1.LoginTime AS DATE)

また、同じ日にユーザーが複数回サインイン/サインアウトする場合にも機能する別のクエリを次に示します。これにより、1 日のすべてのサインイン/サインアウトが一覧表示されます。

;WITH cte1 AS
(
    SELECT  *
            , ROW_NUMBER() OVER 
                (PARTITION BY EmpID, CAST(LoginTime AS DATE) ORDER BY LoginTime) 
                AS num
    FROM    Login
)

SELECT  l1.EmpID
        , l1.LoginTime [SignIn]
        , l2.LoginTime [SignOut]
FROM    cte1 l1
LEFT JOIN   
        cte1 l2 ON 
        l2.EmpID = l1.EmpID
AND     CAST(l2.LoginTime AS DATE) = CAST(l1.LoginTime AS DATE)
AND     l2.num = l1.num + 1
WHERE   l1.status = 'SignIn'

これは、1 日にユーザーの複数のサインイン/サインアウト シナリオを処理する最後の 2 つのクエリのSQL Fiddleです。そのためにEmpID、サンプル データに 102 のユーザーを追加しました。

于 2013-03-07T06:54:27.143 に答える