0

私が働いている会社のデスクトップサポートチームのためにレポートを書いています。レポートは、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))
4

2 に答える 2

2

複数の契約を持つワーカーを取得するには、次を使用します。

select c.workerID
from Contract c
group by c.workerID
having count(distinct contractID) > 1

ただし、新しい開始のもの以外はすべてカウントしたいようです。次のような方法でこれを行うことができます。

select w.workerID
from Contract c
where c.ContractType = 'New'
group by w.workerID
having count(distinct contractID) > 1

テーブルがどのように見えるか、サンプル入力データがどのように見えるか、および達成したい結果の詳細を提供しなかったため、これは実行できる最善のことです。

于 2012-09-06T17:42:05.940 に答える
0
    WHERE ( (dbo.[Contract].StartDate BETWEEN @StartDateF AND @EndDateF)AND dbo.[Contract].Worker_ID 
        IN (select worker_id from dbo.[Contract] 
        group by worker_id 
        having count(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 
   AND dbo.[Contract].Worker_ID = w1.Worker_ID )

今は私のために働いています:)

于 2012-09-07T10:48:06.420 に答える