简体   繁体   English

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

[英]How to exclude some rows on inner / union queries

I have a problem with my SQL queries (I know I'm very bad at this task :( ) 我的SQL查询有问题(我知道我对这个任务很不好:()

Using SLQ Server 2014, I've got a table that stores bank days containing the name of the day and a datetime. 使用SLQ Server 2014,我得到了一个表,用于存储银行日,其中包含日期名称和日期时间。

On the other hand there's a table with technicians that has worked over a project. 另一方面,还有一张桌子,上面有技术人员来完成一个项目。 They could work regular days or even those bank days. 他们可以正常工作甚至是工作日。

I get a query in order to generate payrolls that get all of those technicians that have worked getting techcode, name, project id and date but I need to get another list (UNION) for those all tehcnicians that have not worked during bank holidays because they also need to be inlcuded in the report for payroll (bank days are payed as well but need to be differentiate). 我得到一个查询以生成工资单,以获取所有工作过的技术人员的技术代码,名称,项目ID和日期,但我需要为那些在银行假期期间未工作过的所有技术人员获得另一个列表(UNION),还需要在报告中添加工资单(也支付了银行工作日,但需要区分)。

I tried with joins to get that list that should contain tech code, name, project id and date from Holidays if they didn't work that day (that info is retrieved in the first query because is stored in the Sessions table. The only value that have both tables in common is the date. 我尝试通过join从该假期中获取该列表,该列表应包含“ 假日”中的技术代码,名称,项目ID和日期(如果它们当天无效)(该信息在第一个查询中检索,因为存储在Sessions表中。唯一的值)这两个表的共同点是日期。

I'll give you my queries so far: 到目前为止,我将向您提供我的查询:

-- 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

Holidays contains: 假期包含:

HolidayID   HolidayDate Name.....   
3   2015-08-19 00:00:00.000 August Bank Holiday ...
5   2015-08-20 00:00:00.000 August Bank Holiday ...

For example, for a query like this 例如,对于这样的查询

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)   

I get 我懂了

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

So I would need to get a list showing those technicians but date should be bank holidays date and only if they didn't work during those days so, for example, technician with code 440 must not be in the list twice because he worked on the 20th of August and it should looks like this: 因此,我需要获得一个列表,其中显示那些技术人员,但日期应为银行休假日期,并且仅当他们在那几天没有工作时才如此,例如,代码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

I have tried with UNION, SUB QUERIES, EXIST, IN, INNER and so on I get nothing like that :-/ 我已经尝试了UNION,SUB QUERIES,EXIST,IN,INNER等,但我什么都没得到:-/

A little help will be so thankful. 一点帮助将非常感激。

You can do this in a UNION statement, which connects all technicians to all holidays in the range, but then uses a LEFT JOIN to look up technicians who worked on the holiday and then filters them out if they did. 您可以在UNION语句中执行此操作,该语句将所有技术人员连接到该范围内的所有假期,然后使用LEFT JOIN查找在假期中工作的技术人员,如果有,则将其过滤掉。

See below: 见下文:

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

Well, I finally managed to get the solution (not so difficult for anyone who knows a bit about SQL but a great one for a newcomer like me. 好吧,我终于设法得到了解决方案(对于那些对SQL有所了解的人来说,并不是那么困难,但是对于像我这样的新手来说却是一个很棒的解决方案。

To get only techs who have not been working during bank holidays I had to use "NOT EXISTS" in the second part of the UNION: 为了只让那些在银行假期期间没有工作的技术人员,我不得不在UNION的第二部分中使用“ NOT EXISTS”:

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)
         )

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM