我的SQL查询有问题(我知道我在这个任务上非常糟糕:()
使用SLQ Server 2014,我有一个存储银行工作日的表格,其中包含当天的名称和日期时间。
另一方面,有一个技术人员在一个项目上工作过的桌子。他们可以定期工作甚至是银行工作日。
我得到一个查询,以便生成工资单,让所有技术人员都能获得技术代码,名称,项目ID和日期,但我需要为那些在银行期间没有工作的所有tehcnicians获取另一个列表(UNION)假期因为它们也需要在工资单报告中包括在内(银行工作日也需要支付,但需要区分)。
我尝试使用联接来获取该列表,该列表应该包含技术代码,名称,项目ID和来自 Holidays 的日期,如果他们当天没有工作(该信息在第一天检索到查询因为存储在 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等等,我什么都没得到: - /
一点点帮助会非常感激。
答案 0 :(得分:0)
您可以在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
答案 1 :(得分:0)
好吧,我终于设法得到了解决方案(对于那些对SQL有所了解但对像我这样的新手来说很棒的人来说并不是那么困难。
为了让只有在银行假期没有工作的技术人员,我必须使用&#34; NOT EXISTS&#34;在UNION的第二部分:
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)
)