包含在DATEDIFF()中的SELECT MAX()

时间:2012-09-06 15:53:38

标签: asp.net sql-server-2008 function stored-procedures

我正在为我工​​作的公司的桌面支持团队撰写报告。该报告需要在从ASP.NET应用程序传入的指定时间范围内生成一组新的启动器。目前,我们的Worker表和Contract表之间存在一对多的关系。我们雇用了很多承包商,他们有时会在几个月后回来,但仍然像新的启动器一样对待,因为需要配置新机器和桌面空间。

为每次薪资审核,职位更改和新职位添加新合同。除了新的启动器,我们需要过滤除了所有启动器。为工作变更和薪酬审核添加的最新合同自然是在上一个合同的结束日期之后的一天。因为我只是在一个宏伟的计划中更新鲜,所以我正在努力实现我的目标。

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 

如果当前有效合同与前一个合同有一天不同,我基本上想要在实例中找出一个雇员有多个合同,无论是离开还是回来或支付审查。我的想法应该只给我所有的新手。

麻烦的是,我仍然试图了解何时使用不在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和having子句,但现在我收到以下错误

第15行,第15行,第1行,第24行 关键字'SELECT'附近的语法不正确。 Msg 102,Level 15,State 1,Line 24 ','附近的语法不正确。 Msg 102,Level 15,State 1,Line 24 ')'附近的语法不正确。

这些都与有条款中的功能有关,毫无疑问你可以看到。但是我无法理解这个查询有什么问题,这主要是问题所在。我需要充分理解SQL函数,以便我能够实现正确的解决方案。

我在这里跟进了DATEDIFF()函数http://msdn.microsoft.com/en-us/library/ms189794.aspx

根据MS文档,我可以看到使用此函数中的函数是可以接受的。

修改

注释出Having子句给出了我期望的结果集。它向人们展示合同变更(加薪),但这是没有人应该看到的信息,这些是现在唯一需要过滤掉的记录

修改

我已经做了一些改进并且现在克服了错误信息,但是我仍然让那些已经发生加薪的人。以下是

小组修改后的查询
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))

2 个答案:

答案 0 :(得分: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

因为您没有提供表格的详细信息,样本输入数据的样子以及您想要实现的结果,所以这是最好的。

答案 1 :(得分: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 )

现在适合我:)