Sql 如何排除内部/联合查询中的某些行

Sql 如何排除内部/联合查询中的某些行,sql,sql-server,join,subquery,Sql,Sql Server,Join,Subquery,我的SQL查询有问题(我知道我在这项任务上做得很差:() 使用SLQ Server 2014,我得到了一个存储银行日的表,其中包含日期名称和日期时间 另一方面,在一张桌子上,有一些技术人员在做一个项目,他们可以正常工作,甚至可以在银行工作 我得到一个查询,以便生成工资单,其中包括所有工作过的技术人员的技术代码、姓名、项目id和日期,但我需要获得另一个列表(工会),其中包括所有在银行假日期间未工作过的技术人员,因为他们也需要包含在工资单报告中(银行天数也要支付,但需要区分) 我尝试使用连接来获取该

我的SQL查询有问题(我知道我在这项任务上做得很差:()

使用SLQ Server 2014,我得到了一个存储银行日的表,其中包含日期名称和日期时间

另一方面,在一张桌子上,有一些技术人员在做一个项目,他们可以正常工作,甚至可以在银行工作

我得到一个查询,以便生成工资单,其中包括所有工作过的技术人员的技术代码、姓名、项目id和日期,但我需要获得另一个列表(工会),其中包括所有在银行假日期间未工作过的技术人员,因为他们也需要包含在工资单报告中(银行天数也要支付,但需要区分)

我尝试使用连接来获取该列表,该列表应包含技术代码、名称、项目id和假日日期(如果假日当天不工作)(该信息在第一次查询中检索,因为它存储在Sessions表中。两个表的唯一共同值是date

到目前为止,我将向您提出我的疑问:

-- To get real work hours / days within date range

select 
    distinct s.TechnicianCode, t.Name, s.JobProjectId as jobId, 
    s.SignInDate as [date], 'w'
from 
    JobSession s
inner join 
    Technician t on t.TechnicianCode = s.TechnicianCode
inner join 
    JobAssignedTech jt on jt.TechCode = s.TechnicianCode
left join 
    LeaveDate ld on ld.TechnicianCode = s.TechnicianCode
where  
    (cast(s.SignInDate as date) >= cast(@DateFrom as date) 
    and cast(s.SignInDate as date) <= cast(@DateTo as date)) 
    and jt.IsActive = 1
例如,对于这样的查询

select  
    distinct s.TechnicianCode, t.Name, s.JobProjectId, s.SignInDate  
from 
    JobSession s
inner join 
    Technician t on s.TechnicianCode = t.TechnicianCode 
where 
    cast(s.SignInDate as date) between cast('2015/08/17' as date) and cast('2015/08/24' as date)   
我明白了

TechnicianCode  Name                JobProjectId            SignInDate
    282                 Patrick Flood       TEST JOB CHQ E2443      2015-08-17          
    332                 Anthony Farrell     TEST JOB CHQ E2443      2015-08-17
    342                 Ciaran Kimmage      TEST JOB CHQ E2443      2015-08-17
    343                 Anthony Clinton     TEST JOB CHQ E2443      2015-08-17
    440                 Darragh Byrne       TEST JOB CHQ E2443      2015-08-17
    440                 Darragh Byrne       TEST JOB CHQ E2443      2015-08-20
    489                 Thomas Cunningham   TEST JOB CHQ E2443      2015-08-17
    491                 Aidan Lee           TEST JOB CHQ E2443      2015-08-17
    497                 Brian Canavan       TEST JOB CHQ E2443      2015-08-17
    TE                  Test                Sandyford site 07.15    2015-08-17
因此,我需要得到一份显示这些技术人员的列表,但日期应为银行假期日期,且仅当他们在这些天内未工作时,因此,例如,代码为440的技术人员不得在列表中出现两次,因为他在8月20日工作,其应如下所示:

TechnicianCode  Name                JobProjectId            SignInDate
        282                 Patrick Flood       TEST JOB CHQ E2443      2015-08-19          
        282                 Patrick Flood       TEST JOB CHQ E2443      2015-08-20          
        332                 Anthony Farrell     TEST JOB CHQ E2443      2015-08-19
        332                 Anthony Farrell     TEST JOB CHQ E2443      2015-08-20
        342                 Ciaran Kimmage      TEST JOB CHQ E2443      2015-08-19
        342                 Ciaran Kimmage      TEST JOB CHQ E2443      2015-08-20
        343                 Anthony Clinton     TEST JOB CHQ E2443      2015-08-19
        343                 Anthony Clinton     TEST JOB CHQ E2443      2015-08-20
        440                 Darragh Byrne       TEST JOB CHQ E2443      2015-08-19        
        489                 Thomas Cunningham   TEST JOB CHQ E2443      2015-08-19
        489                 Thomas Cunningham   TEST JOB CHQ E2443      2015-08-20
        491                 Aidan Lee           TEST JOB CHQ E2443      2015-08-19
        491                 Aidan Lee           TEST JOB CHQ E2443      2015-08-20
        497                 Brian Canavan       TEST JOB CHQ E2443      2015-08-19
        497                 Brian Canavan       TEST JOB CHQ E2443      2015-08-19
        TE                  Test                Sandyford site 07.15    2015-08-19
        TE                  Test                Sandyford site 07.15    2015-08-20
我尝试过联合、子查询、存在、在、内部等等,但没有得到这样的结果:-/


一点帮助将是非常感谢的。

您可以在一个
联合
语句中实现这一点,该语句将所有技术人员连接到范围内的所有假日,但随后使用
左连接
查找在假日工作的技术人员,如果他们在假日工作,则过滤掉他们

见下文:

select  distinct 
    s.TechnicianCode, 
    t.Name, 
    s.JobProjectId, 
    s.SignInDate  
from 
    JobSession s
inner join 
    Technician t on s.TechnicianCode = t.TechnicianCode 
where 
    cast(s.SignInDate as date) between cast('2015/08/17' as date) and cast('2015/08/24' as date) 

UNION 

SELECT 
    t.TehnicianCode,
    t.Name,
    NULL AS JobProjectID,
    h.HolidayDate 
FROM 
    Technician t 
     INNER JOIN 
    Holidays h ON 
        h.HolidayDate BETWEEN cast('2015/08/17' as date) and cast('2015/08/24' as date) -- connect every technician to every holiday in the range
     LEFT JOIN 
    JobSession s ON -- check for technicians who worked on the holiday
        t.TechnicianCode = s.TechnicianCode AND 
        cast(s.SignInDate as date) = h.HolidayDate
WHERE s.TechnicianCode IS NULL -- filter out the technicans who worked on the holiday

嗯,我终于找到了解决方案(对任何一个懂一点SQL的人来说都不难,但对像我这样的新手来说,这是一个很好的解决方案)

为了只获得在银行假期期间没有工作的技术人员,我必须在工会的第二部分中使用“不存在”:

select distinct(s.TechnicianCode), t.Name, jt.JobProjectId as jobId, cast(h.HolidayDate as date) as date, 'h'---this is to know if tech has worked or was on holidays
        from Holidays h, JobSession s
        inner join Technician t  on s.TechnicianCode = t.TechnicianCode
        inner join JobAssignedTech jt on jt.TechCode = t.TechnicianCode
        where cast(h.HolidayDate as date)  between cast(@DateFrom as date) and cast(@DateTo as date) 
            and cast(s.SignInDate as date)  between cast(@DateFrom as date) and cast(@DateTo as date) 
            and jt.IsActive = 1
            and  not exists (
        Select *--, JobProjectId, SignInDate , h.HolidayDate, h.Name
         from JobSession s1
             where cast(s1.SignInDate as date)  between cast(@DateFrom as date) and cast(@DateTo as date)    
             and s1.TechnicianCode = s.TechnicianCode and cast(s1.SignIndate as date) = cast(h.HolidayDate as date)
         )

DISTINCT不是列上的函数,它作用于整个选定行!!!(即“选择DISTINCT(c1)”,c2“eq”选择DISTINCT c1,c2“eq”选择DISTINCT c1,(c2)”…(它实际上是选择DISTINCT,与选择[全部]相反。)我也必须重复这一点。
DISTINCT
不是一个函数。另外:您使用的是哪种数据库管理系统?Postgres?Oracle?与假日的连接在哪里?唯一可用的连接是槽日期时间(强制转换为日期)。目标是获得一个完整的列表,其中包含已工作(日期存储到会话中)但未工作的技术(没有存储任何数据,他们只是没有当天的会话,因此没有可用信息,我必须使用假日日期进行构建。非常感谢您的帮助。它起到了作用!。我也找到了解决方案;我以前几乎就在那里,但在条件方面犯了一个错误。
select distinct(s.TechnicianCode), t.Name, jt.JobProjectId as jobId, cast(h.HolidayDate as date) as date, 'h'---this is to know if tech has worked or was on holidays
        from Holidays h, JobSession s
        inner join Technician t  on s.TechnicianCode = t.TechnicianCode
        inner join JobAssignedTech jt on jt.TechCode = t.TechnicianCode
        where cast(h.HolidayDate as date)  between cast(@DateFrom as date) and cast(@DateTo as date) 
            and cast(s.SignInDate as date)  between cast(@DateFrom as date) and cast(@DateTo as date) 
            and jt.IsActive = 1
            and  not exists (
        Select *--, JobProjectId, SignInDate , h.HolidayDate, h.Name
         from JobSession s1
             where cast(s1.SignInDate as date)  between cast(@DateFrom as date) and cast(@DateTo as date)    
             and s1.TechnicianCode = s.TechnicianCode and cast(s1.SignIndate as date) = cast(h.HolidayDate as date)
         )