2017-01-18 4 views
0

私の会社のすべてのユーザーを一覧表示するテーブルがあります。各職員がどのように雇用されたかを示す複数のエントリーがあります。SQL Serverの複数の行にまたがる2つの日付間の時間を追加します

RowID UserID FirstName LastName Title  StartDate Active EndDate 
----------------------------------------------------------------------------------- 
1  1  John  Smith  Manager 2017-01-01 0  2017-01-31 
2  1  John  Smith  Director 2017-02-01 0  2017-02-28 
3  1  John  Smith  CEO  2017-03-01 1  NULL 
4  2  Sam   Davey  Manager 2017-01-01 0  2017-02-28 
5  2  Sam   Davey  Manager 2017-03-01 0  NULL 
6  3  Hugh  Holland  Admin  2017-02-01 1  NULL 
7  4  David  Smith  Admin  2017-01-01 0  2017-02-28 

いつでもサービスの長さを教えてくれるクエリを作成しようとしています。

私は自分の情報は、私は複数の行を結合する必要がある時間の経過とともに変化して一人の人間が複数の行で表されているように問題を抱えてい一環...

私はで採用されている者に報告するためのクエリを持っています私が得た限りの時点である。

DECLARE @DateCheck datetime 
SET @DateCheck = '2017/05/10' 

SELECT * 
FROM UsersTest 
WHERE @DateCheck >= StartDate AND @DateCheck <= ISNULL(EndDate, @DateCheck) 
+0

ここでの本当の課題であるあなたが持つ従業員表を持っている必要があります。雇用日の列。次に別のテーブルにあなたの履歴があります。EmployeePositionのようなもので、そのポジションの開始日と終了日があります。名前が変わります。 –

+0

私はそれを整理する最善の方法として、これまでに別の質問をしました。 RowID、UserID、StartDate、EndDateを除くすべての列を無視するのに役立ちます。この考え方は、提供された日付の値に従って現在のレコードの情報のみを返すことになります。 – Zac

+0

うまくいえば、あなたの最後の質問であなたの正規化を使って設計上の欠陥を指摘してくれたらと思っています。クエリに苦労している理由は、アーキテクチャに欠陥があるためです。これが適切に正規化されていれば、クエリーは非常に簡単になります。 –

答えて

4

だ試してみてください。キーは、適切な番号(日、月、年)を選択することになります。戻り値は整数なので、年を選択すると丸められます(覚えておくと、要約ではなくレコードごとに丸められます)。以下の月が選択されました。

WITH CurrentName AS 
    (SELECT UserID, FirstName, LastName 
    from 
    UserStartStop 
    where Active = 1 -- You can replace this with a date check 
) 

SELECT uss.UserID, 
    MAX(cn.FirstName) as FirstName, -- the max is necessary because we are 
            -- grouping. Could include in group by 
    MAX(cn.LastName) as LastName, 
    SUM(DATEDIFF(mm,uss.StartDate,COALESCE(uss.EndDate,GETDATE()))) 
    from UserStartStop uss 
    JOIN CurrentName cn 
    on uss.UserID = cn.UserID 
GROUP BY UserID 
order by UserID 
+1

DateDiffは丸められません。 2つの日付の間に渡された日付しきい値の数をカウントします。問合せは必要な処理を行いますが、説明は正しくありません。 –

+1

私は忘れて、あとで実現しました。いずれにせよ、いずれの説明でも、私は日数を使い、365で割って年にするべきであることを認識しました。月を使用すると丸め誤差が多すぎる –

+0

ありがとう!どのようにして、私はいつも日付に関して最新の行を返すようにしますか?私はGETDATE()を@DateCheckに変更し、mmをDDに変更しました。 – Zac

-2

それはあなたがDATEDIFF関数を使用する必要が

Select 
FirstName, 
LastName, 
Min(StartDate)StartDate, 
Max(isnull(EndDate,getdate()) as EndDate 
    from Table 
+0

ここにGroup By節がないため、これは機能しません。 –

1

サービスの月については、「ミリメートル」に変更「D」:ユーザー名のためにあなたのデータは正規化されていないので、

Create table #UsersTest (
     RowId int 
    , UserID int 
    , FirstName nvarchar(100) 
    , LastName nvarchar(100) 
    , Title nvarchar(100) 
    , StartDate date 
    , Active bit 
    , EndDate date) 

Insert #UsersTest values (1, 1, 'John', 'Smith', 'Manager', '2017-01-01', 0, '2017-01-31') 
Insert #UsersTest values (1, 1, 'John', 'Smith', 'Director', '2017-02-01', 0, '2017-02-28') 
Insert #UsersTest values (1, 1, 'John', 'Smith', 'CEO', '2017-03-01', 1, null) 
Insert #UsersTest values (1, 2, 'Sam', 'Davey', 'Manager', '2017-01-01', 0, '2017-02-28') 
Insert #UsersTest values (1, 2, 'Sam', 'Davey', 'Manager', '2017-03-01', 0, null) 
Insert #UsersTest values (1, 3, 'Hugh', 'Holland', 'Admin', '2017-02-01', 1, null) 
Insert #UsersTest values (1, 4, 'David', 'Smith', 'Admin', '2017-01-01', 0, '2017-02-28') 

Declare @DateCheck as datetime = '2017/05/10' 
Select UserID, FirstName, LastName 
    , Datediff(d, Min([StartDate]), iif(isnull(Max([EndDate]),'1900-01-01')<@DateCheck, @DateCheck ,Max([Enddate]))) as [LengthOfService] 
from #UsersTest 
Group by UserID, FirstName, LastName 
+0

DateCheckを@DateCheckに変更しなければなりませんでした.MaxdateはEndDateであると想定していますか?それが事実です。私はUserID 3に対して正しい答えを得て、他のすべては129日として表示します。 – Zac

+0

@Zacこれらの修正を含むように変更しました。 – cloudsafe

関連する問題