【问题标题】:How to exclude some rows on inner / union queries如何排除内部/联合查询中的某些行
【发布时间】:2015-08-27 11:41:03
【问题描述】:

我的 SQL 查询有问题(我知道我不擅长这项任务 :()

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

另一方面,有一张桌子,上面有参与过项目的技术人员。他们可以正常工作,甚至可以在银行工作日工作。

我收到一个查询,以便生成工资单,让所有工作过的技术人员获取技术代码、名称、项目 ID 和日期,但我需要为那些在银行期间没有工作过的技术人员获取另一个列表 (UNION)假期,因为它们也需要包含在工资单的报告中(银行工作日也被支付,但需要加以区分)。

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

到目前为止,我会给你我的疑问:

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

假期包含:

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

例如,对于这样的查询

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

我尝试过使用 UNION、SUB QUERIES、EXIST、IN、INNER 等等,但没有得到类似的结果:-/

稍有帮助将不胜感激。

【问题讨论】:

  • DISTINCT 不是列上的函数,它适用于整个选定的行!!! (即 "select distinct (c1), c2" eq "select distinct c1, c2" eq "select distinct c1, (c2)" ...(实际上是 SELECT DISTINCT,与 SELECT [ALL] 相反。)跨度>
  • 我也必须重复一遍。 DISTINCTNOT 函数。另外:您使用的是哪个 DBMS?后格雷斯?甲骨文?
  • Holidays 的连接在哪里?
  • 唯一可用的连接是通过日期时间(转换为日期)。目标是获得一个完整的列表,其中包含已经工作的技术(日期存储在会话中)并且没有工作(没有存储数据,他们当天没有会话,所以没有可用的信息,我必须使用假期日期构建.

标签: sql sql-server join subquery


【解决方案1】:

您可以在 UNION 语句中执行此操作,该语句将所有技术人员连接到该范围内的所有假期,然后使用 LEFT JOIN 查找在假期工作的技术人员,然后将他们过滤掉。

见下文:

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

【讨论】:

  • 非常感谢您的帮助。有效!。我也找到了解决方案;我之前就快到那里了,但在条件上犯了一个错误。
【解决方案2】:

好吧,我终于设法得到了解决方案(对于了解一点 SQL 的人来说并不难,但对于像我这样的新手来说却是一个很好的解决方案。

为了只获得在银行假期没有工作的技术人员,我不得不在 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)
         )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-23
    • 2014-12-16
    • 1970-01-01
    • 2021-08-12
    • 2018-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多