此查询稍微复杂一些,但出于简单原因,我将其发布得尽可能简单
我有1个具有以下各列的表
表:“ time_TimesheetRow” 列:
TimeSheet_ID,
d1,
d2,
d3,
d4,
d5,
d6,
d7,
rate
现在,我的选择带来了很多字段,其中包括以下字段:
time_TimesheetRow.d3 AS [Monday Normal Hours],
time_TimesheetRow.d4 AS [Tuesday Normal Hours],
time_TimesheetRow.d5 AS [Wednesday Normal Hours],
time_TimesheetRow.d6 AS [Thursday Normal Hours],
time_TimesheetRow.d7 AS [Friday Normal Hours],
time_TimesheetRow.d1 AS [Saturday Normal Hours],
time_TimesheetRow.d2 AS [Sunday Normal Hours],
time_TimesheetRow.d3 AS [Monday OT Hours],
time_TimesheetRow.d4 AS [Tuesday OT Hours],
time_TimesheetRow.d5 AS [Wednesday OT Hours],
time_TimesheetRow.d6 AS [Thursday OT Hours],
time_TimesheetRow.d7 AS [Friday OT Hours],
time_TimesheetRow.d1 AS [Saturday OT Hours],
time_TimesheetRow.d2 AS [Sunday OT Hours]
但是,事实是所有正常时间都是费率= 0的时间 OT列是速率<> 0
的列该怎么办?
我试图在FROM子句中添加具有不同别名的同一张表,然后使用ID字段进行匹配,但似乎不起作用
这是完整的查询,这将给出一个清晰的示例。
SELECT ts1.TimeSheetRow_ID AS [Unique Line Id],
peperson.PERSONNEL_NO AS [Staff Id],
peperson.SURNAME + ', ' + peperson.FORENAME AS [Forename + Surname],
time_Timesheet.TSDate AS [Week ending date],
ts2.d1 + ts2.d2 + ts2.d3 + ts2.d4 + ts2.d5 + ts2.d6 + ts2.d7 AS [Normal Hours],
ts3.d1 + ts3.d2 + ts3.d3 + ts3.d4 + ts3.d5 + ts3.d6 + ts3.d7 AS [Overtime Hours],
ts2.d1 + ts2.d2 + ts2.d3 + ts2.d4 + ts2.d5 + ts2.d6 + ts2.d7 + ts3.d1 + ts3.d2 + ts3.d3 + ts3.d4 + ts3.d5 + ts3.d6 + ts3.d7 AS [Total Hours],
CASE
WHEN ts1.Rate = 11
THEN 'Unpaid'
ELSE 'Paid'
END AS [Overtime Paid/Unpaid Indicator],
ts1.notes AS Narrative,
ts1.Job AS [Job Number],
ts2.d3 AS [Monday Normal Hours],
ts2.d4 AS [Tuesday Normal Hours],
ts2.d5 AS [Wednesday Normal Hours],
ts2.d6 AS [Thursday Normal Hours],
ts2.d7 AS [Friday Normal Hours],
ts2.d1 AS [Saturday Normal Hours],
ts2.d2 AS [Sunday Normal Hours],
ts3.d3 AS [Monday OT Hours],
ts3.d4 AS [Tuesday OT Hours],
ts3.d5 AS [Wednesday OT Hours],
ts3.d6 AS [Thursday OT Hours],
ts3.d7 AS [Friday OT Hours],
ts3.d1 AS [Saturday OT Hours],
ts3.d2 AS [Sunday OT Hours],
peperson.hourly_rate AS [Staff Overhead Rate],
peperson.hourly_rate AS [Cost Rate],
peperson.PU AS [Staff Cost Centre Code],
peperson.PU_DESCRIPTION AS [Staff Cost Centre Name]
FROM dbo.time_manager
INNER JOIN dbo.peperson peperson_manager ON dbo.time_manager.manager_payroll = peperson_manager.Personnel_no
RIGHT OUTER JOIN dbo.time_Timesheet
INNER JOIN dbo.time_TimesheetRow ts1 ON dbo.time_Timesheet.TimeSheet_ID = ts1.TimeSheet_ID
INNER JOIN dbo.time_TimesheetRow ts2 ON dbo.time_Timesheet.TimeSheet_ID = ts2.TimeSheet_ID
AND ts2.rate IN(0)
INNER JOIN dbo.time_TimesheetRow ts3 ON dbo.time_Timesheet.TimeSheet_ID = ts3.TimeSheet_ID
AND ts3.rate NOT IN(0)
INNER JOIN dbo.peperson ON dbo.time_Timesheet.Payroll = dbo.peperson.Personnel_no
INNER JOIN dbo.time_Status ON dbo.time_Timesheet.StatusID = dbo.time_Status.statusID ON dbo.time_manager.payroll = dbo.time_Timesheet.Payroll
WHERE time_Timesheet.TSDate > '2019-11-01'
AND ts1.Job LIKE 'B23639%';
现在看来查询有点问题,因为带来的行太少了,当它应该带来更多的数据时,我用 dbo.time_TimesheetRow ts2 和 dbo.time_TimesheetRow ts3 表,它带来了很多东西,所以我在想这里是错误所在
添加了@LukStorms建议的逻辑:
SELECT ts1.TimeSheetRow_ID AS [Unique Line Id],
peperson.PERSONNEL_NO AS [Staff Id],
peperson.SURNAME + ', ' + peperson.FORENAME AS [Forename + Surname],
time_Timesheet.TSDate AS [Week ending date],
ts1.d1 + ts1.d2 + ts1.d3 + ts1.d4 + ts1.d5 + ts1.d6 + ts1.d7 AS [Normal Hours],
ts2.d1 + ts2.d2 + ts2.d3 + ts2.d4 + ts2.d5 + ts2.d6 + ts2.d7 AS [Overtime Hours],
ts1.d1 + ts1.d2 + ts1.d3 + ts1.d4 + ts1.d5 + ts1.d6 + ts1.d7 + ts2.d1 + ts2.d2 + ts2.d3 + ts2.d4 + ts2.d5 + ts2.d6 + ts2.d7 AS [Total Hours],
CASE
WHEN ts1.Rate = 11
THEN 'Unpaid'
ELSE 'Paid'
END AS [Overtime Paid/Unpaid Indicator],
ts1.notes AS Narrative,
ts1.Job AS [Job Number],
ts1.d3 AS [Monday Normal Hours],
ts1.d4 AS [Tuesday Normal Hours],
ts1.d5 AS [Wednesday Normal Hours],
ts1.d6 AS [Thursday Normal Hours],
ts1.d7 AS [Friday Normal Hours],
ts1.d1 AS [Saturday Normal Hours],
ts1.d2 AS [Sunday Normal Hours],
ts2.d3 AS [Monday OT Hours],
ts2.d4 AS [Tuesday OT Hours],
ts2.d5 AS [Wednesday OT Hours],
ts2.d6 AS [Thursday OT Hours],
ts2.d7 AS [Friday OT Hours],
ts2.d1 AS [Saturday OT Hours],
ts2.d2 AS [Sunday OT Hours],
peperson.hourly_rate AS [Staff Overhead Rate],
peperson.hourly_rate AS [Cost Rate],
peperson.PU AS [Staff Cost Centre Code],
peperson.PU_DESCRIPTION AS [Staff Cost Centre Name]
FROM dbo.time_manager
INNER JOIN dbo.peperson peperson_manager ON dbo.time_manager.manager_payroll = peperson_manager.Personnel_no
RIGHT OUTER JOIN dbo.time_Timesheet
INNER JOIN dbo.time_TimesheetRow ts1 ON dbo.time_Timesheet.TimeSheet_ID = ts1.TimeSheet_ID
AND ts1.Rate = 0
LEFT JOIN dbo.time_TimesheetRow ts2 ON dbo.time_Timesheet.TimeSheet_ID = ts2.TimeSheet_ID
AND ts2.rate > 0
INNER JOIN dbo.peperson ON dbo.time_Timesheet.Payroll = dbo.peperson.Personnel_no
INNER JOIN dbo.time_Status ON dbo.time_Timesheet.StatusID = dbo.time_Status.statusID ON dbo.time_manager.payroll = dbo.time_Timesheet.Payroll
WHERE time_Timesheet.TSDate > '2019-11-01'
AND ts1.Job LIKE 'B23639%';
我仍然遇到以下问题:加班时间,总小时和所有 OT小时列均显示NULL作为值>
答案 0 :(得分:1)
因此,您要根据ID和费率进行自我加入
SELECT
t0.TimeSheet_ID,
t0.d3 AS [Monday Normal Hours],
t0.d4 AS [Tuesday Normal Hours],
t0.d5 AS [Wednesday Normal Hours],
t0.d6 AS [Thursday Normal Hours],
t0.d7 AS [Friday Normal Hours],
t0.d1 AS [Saturday Normal Hours],
t0.d2 AS [Sunday Normal Hours],
SUM(tx.d3) AS [Monday OT Hours],
SUM(tx.d4) AS [Tuesday OT Hours],
SUM(tx.d5) AS [Wednesday OT Hours],
SUM(tx.d6) AS [Thursday OT Hours],
SUM(tx.d7) AS [Friday OT Hours],
SUM(tx.d1) AS [Saturday OT Hours],
SUM(tx.d2) AS [Sunday OT Hours]
FROM time_TimesheetRow t0
LEFT JOIN time_TimesheetRow tx
ON tx.TimeSheet_ID = t0.TimeSheet_ID
AND tx.rate > 0
WHERE t0.rate = 0
GROUP BY t0.TimeSheet_ID, t0.d1, t0.d2, t0.d3, t0.d4, t0.d5, t0.d6, t0.d7
ORDER BY t0.TimeSheet_ID
未经测试的记事本涂鸦,它基于未简化查询的重塑版本:
SELECT
ts.TimeSheetRow_ID AS [Unique Line Id],
pep.PERSONNEL_NO AS [Staff Id],
CONCAT(pep.SURNAME, ', ' + pep.FORENAME) AS [Forename + Surname],
ts.TSDate AS [Week ending date],
t0tot.Total AS [Normal Hours],
ISNULL(txtot.Total,0) AS [Overtime Hours],
t0tot.Total + ISNULL(txtot.Total,0) AS [Total Hours],
CASE WHEN ts.Rate = 11 THEN 'Unpaid' ELSE 'Paid' END AS [Overtime Paid/Unpaid Indicator],
t0.notes AS [Narrative],
t0.Job AS [Job Number],
t0.d3 AS [Monday Normal Hours],
t0.d4 AS [Tuesday Normal Hours],
t0.d5 AS [Wednesday Normal Hours],
t0.d6 AS [Thursday Normal Hours],
t0.d7 AS [Friday Normal Hours],
t0.d1 AS [Saturday Normal Hours],
t0.d2 AS [Sunday Normal Hours],
tx.d3 AS [Monday OT Hours],
tx.d4 AS [Tuesday OT Hours],
tx.d5 AS [Wednesday OT Hours],
tx.d6 AS [Thursday OT Hours],
tx.d7 AS [Friday OT Hours],
tx.d1 AS [Saturday OT Hours],
tx.d2 AS [Sunday OT Hours],
pep.hourly_rate AS [Staff Overhead Rate],
pep.hourly_rate AS [Cost Rate],
pep.PU AS [Staff Cost Centre Code],
pep.PU_DESCRIPTION AS [Staff Cost Centre Name]
FROM dbo.time_Timesheet AS ts
INNER JOIN dbo.time_manager AS tm_mngr
ON tm_mngr.payroll = ts.Payroll
INNER JOIN dbo.peperson AS pep_mngr
ON pep_mngr.Personnel_no = tm_mngr.manager_payroll
INNER JOIN dbo.peperson AS pep
ON pep.Personnel_no = ts.Payroll
INNER JOIN dbo.time_Status AS tm_stat
ON tm_stat.statusID = ts.StatusID
INNER JOIN dbo.time_TimesheetRow AS t0
ON t0.TimeSheet_ID = ts.TimeSheet_ID
AND t0.Rate = 0
LEFT JOIN dbo.time_TimesheetRow tx
ON tx.TimeSheet_ID = ts.TimeSheet_ID
AND (tx.rate > 0 OR tx.rate IS NULL)
OUTER APPLY (SELECT SUM(d) Total FROM (VALUES (t0.d1),(t0.d2),(t0.d3),(t0.d4),(t0.d5),(t0.d6),(t0.d7)) t(d)) AS t0tot
OUTER APPLY (SELECT SUM(d) Total FROM (VALUES (tx.d1),(tx.d2),(tx.d3),(tx.d4),(tx.d5),(tx.d6),(tx.d7)) t(d)) AS txtot
WHERE ts.TSDate > '2019-11-01'
AND t0.Job LIKE 'B23639%';
基本上,更多使用短别名。
并且不使用RIGHT JOIN
,因为这经常会造成混淆。
而外部适用于对d求和。
答案 1 :(得分:1)
您选择的行
INNER JOIN dbo.time_TimesheetRow ts2 ON dbo.time_Timesheet.TimeSheet_ID = ts2.TimeSheet_ID
AND ts2.rate IN(0)
INNER JOIN dbo.time_TimesheetRow ts3 ON dbo.time_Timesheet.TimeSheet_ID = ts3.TimeSheet_ID
AND ts3.rate NOT IN(0)
缩小结果集的范围,因为内部联接要求所有设置项都应从两侧都包括在联接列中 并用
限制设置rate (NOT) IN(0)
这意味着只会将具有此类值的结果添加到集合中。
我建议使用左右连接,因为并非所有行的所有数据的费率都为“(0)”或“非(0)”。
我不确定您知道自己在做什么,因为在查询中间添加右外部联接似乎很不寻常,因为稍后您添加左联接。
对于您的加班时间,总小时和所有 OT小时问题,在添加之前,请使用ISNULL(value,0),您可以使用
进行检查select 1+null+1
NULL和数字的总和始终为