根据条件在不同的列中选择

时间:2019-12-03 14:59:49

标签: sql tsql

此查询稍微复杂一些,但出于简单原因,我将其发布得尽可能简单

我有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作为值

2 个答案:

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

这意味着只会将具有此类值的结果添加到集合中。

inner join Vien diagram

我建议使用左右连接,因为并非所有行的所有数据的费率都为“(0)”或“非(0)”。

我不确定您知道自己在做什么,因为在查询中间添加右外部联接似乎很不寻常,因为稍后您添加左联接。

对于您的加班时间总小时和所有 OT小时问题,在添加之前,请使用ISNULL(value,0),您可以使用

进行检查
select 1+null+1

NULL和数字的总和始终为