私が働いている会社のデスクトップサポートチームのためにレポートを書いています。レポートは、ASP.NETアプリケーションから渡された指定された時間枠内に一連の新しいスターターを生成する必要があります。現在、WorkerテーブルとContractテーブルの間には1対多の関係があります。私たちは多くの請負業者を雇っており、彼らは数ヶ月後に戻ってくることもありますが、新しいマシンをデスクスペースと一緒に構成する必要があるため、新しいスターターのように扱われます。
給与レビュー、役職の変更、新しいスターターごとに新しい契約が追加されます。新しいスターター以外のすべてを除外する必要があります。転職・支払い審査のために追加される最新の契約は、当然、前回の契約終了日の翌日となります。私は物事の壮大な計画にまだ新鮮であるだけなので、私は自分の目標を達成するために使用しようとしている一連の機能に苦労しています。
WHERE
(dbo.[Contract].StartDate BETWEEN @StartDateF AND @EndDateF) AND DATEDIFF(day, SELECT MAX(StartDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID, SELECT MAX(EndDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID)> 1
基本的に、現在のアクティブな契約が前の契約と1日異なる場合、退職して戻ってくるかレビューを支払うかに関係なく、従業員が複数の契約を結んでいる場合を確認したいと思います。これは私の考えでは、すべての新しいスターターだけを私に与えるはずです。
問題は、selectにない集計関数を使用する場合と、HAVING句を適用する場合に頭を悩ませようとしていることです。
私の理解不足がこのクエリ/ロジックの失敗の原因である理由を理解するのに役立つ助けをいただければ幸いです。
ありがとう
編集
わかりました、私はまだこの解決策を打ちのめしています、そしてこれは構文的に間違っています。ここでのあいまいさの一部を取り除くための試みは、更新を伴うクエリです。
Declare @StartDateF varchar(10)
Set @StartDateF = '2012-08-03'
Declare @EndDateF varchar(10)
Set @EndDateF = '2012-09-04'
SELECT w1.Worker_ID, w1.Title, w1.FirstName, w1.Surname,w1.Gender, w1.DateofBirth,
dbo.[Contract].StartDate, (select w2.surname + ',' + w2.firstname from worker w2 WITH (NOLOCK) where w2.worker_ID = w1.manager)as Manager, dbo.Grade.GradeDescription AS JobTitle, dbo.Grade.Discipline,
CASE WHEN dbo.[Contract].ContractType_ID = 1 OR dbo.[Contract].ContractType_ID = 2 OR dbo.[Contract].ContractType_ID = 5 OR dbo.[Contract].ContractType_ID = 6
THEN 'Staff' ELSE 'Contractor' END AS ContractType
FROM dbo.Worker w1 WITH (NOLOCK) inner join
dbo.[Contract] WITH (NOLOCK) ON dbo.[Contract].Worker_ID = w1.Worker_ID inner join
dbo.Grade WITH (NOLOCK) ON dbo.Grade.Grade_ID = dbo.[Contract].Grade_ID
WHERE
(dbo.[Contract].StartDate BETWEEN @StartDateF AND @EndDateF AND EndDate IS NULL)
group by
w1.Worker_ID, w1.Title, w1.FirstName, w1.Surname,w1.Gender, w1.DateofBirth,
dbo.[Contract].StartDate, manager, dbo.Grade.Discipline,dbo.Grade.GradeDescription, dbo.[Contract].ContractType_ID
Having DATEDIFF(day, SELECT MAX(StartDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID, SELECT MAX(EndDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID)
group byとhave句を追加しましたが、次のエラーが発生します
メッセージ156、レベル15、状態1、行24キーワード「SELECT」の近くの構文が正しくありません。メッセージ102、レベル15、状態1、行24'、'の近くの構文が正しくありません。メッセージ102、レベル15、状態1、行24')'の近くの構文が正しくありません。
これらはすべて、あなたが見ることができる間違いなく、having節の関数に関連しています。しかし、私はこのクエリの何が問題なのか理解できず、これが主に質問です。正しいソリューションを実装できるように、SQL関数を十分に理解する必要があります。
ここでDATEDIFF()関数をフォローアップしましたhttp://msdn.microsoft.com/en-us/library/ms189794.aspx
MSのドキュメントによると、この関数内で関数を使用することは許容できることがわかります。
編集
Have句をコメントアウトすると、期待する結果セットが得られます。契約に変更があった人(昇給)が表示されていますが、これは誰も見るべきではない情報です。これらは現在、除外する必要がある唯一のレコードです。
編集
私はいくつかの改善を行い、エラーメッセージを克服しましたが、それでも昇給が発生した人々を獲得しています。これは、グループからの修正されたクエリです。
group by
w1.Worker_ID, w1.Title, w1.FirstName, w1.Surname,w1.Gender, w1.DateofBirth,
dbo.[Contract].StartDate, manager, dbo.Grade.Discipline,dbo.Grade.GradeDescription, dbo.[Contract].ContractType_ID, w1.Worker_ID
Having
(((dbo.[Contract].StartDate BETWEEN @StartDateF AND @EndDateF)
AND COUNT(dbo.[Contract].Worker_ID) = 1)
OR
((dbo.[Contract].StartDate BETWEEN @StartDateF AND @EndDateF)
AND DATEDIFF(day, (SELECT MAX(EndDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID), (SELECT MAX(StartDate)FROM dbo.[Contract] WHERE dbo.[Contract].Worker_ID = w1.Worker_ID))>1))