Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 以升序求和,突破和的极限_Sql_Oracle_Row - Fatal编程技术网

Sql 以升序求和,突破和的极限

Sql 以升序求和,突破和的极限,sql,oracle,row,Sql,Oracle,Row,我试图用SQL计算小时数,但我不能简单地求和。求和需要按升序进行,当它达到边界限制时,它将在另一列或行中继续求和 我掌握的数据如下: Employee_Id | Date | Overtime_Day | Overtime_Night 48 | 05/03/2014 | 3 hours | 4 hours 48 | 05/04/2014 | 9 hours | 1 hours 48 | 05/1

我试图用SQL计算小时数,但我不能简单地求和。求和需要按升序进行,当它达到边界限制时,它将在另一列或行中继续求和

我掌握的数据如下:

Employee_Id |    Date     | Overtime_Day | Overtime_Night
48          |  05/03/2014 |   3 hours    |   4 hours
48          |  05/04/2014 |   9 hours    |   1 hours
48          |  05/10/2014 |   1 hours    |   1 hours
48          |  05/20/2014 |   9 hours    |   4 hours
            |             |= 22 hours    | = 10 hours
Overtime (Day+Night) 50%: from 0 to 15
Overtime (Day+Night) 100%: > 15
总和的边界如下所示:

Employee_Id |    Date     | Overtime_Day | Overtime_Night
48          |  05/03/2014 |   3 hours    |   4 hours
48          |  05/04/2014 |   9 hours    |   1 hours
48          |  05/10/2014 |   1 hours    |   1 hours
48          |  05/20/2014 |   9 hours    |   4 hours
            |             |= 22 hours    | = 10 hours
Overtime (Day+Night) 50%: from 0 to 15
Overtime (Day+Night) 100%: > 15
但我也需要知道是白天还是晚上

Overtime 50% is all hours from 0 to 15, no matter if it's day or night:
3 hours [05/03/2014] [Day]
4 hours [05/03/2014] [Night]
8 hours [05/04/2014] [Day] (2 hours is left for this day, left hours and next hours will be 100%)
Overtime 100% is all hours above 15:
1 hours [05/04/2014] [Day]
1 hours [05/04/2014] [Night]
1 hours [05/10/2014] [Day]
1 hours [05/10/2014] [Night]
9 hours [05/20/2014] [Day]
4 hours [05/20/2014] [Night]
WITH DATA AS (           
SELECT 48 AS EMPLOYEE_ID, '05/03/2014' AS "DATE", 3 AS OVERTIME_DAY, 4 AS OVERTIME_NIGHT FROM DUAL UNION
SELECT 48 AS EMPLOYEE_ID, '05/04/2014' AS "DATE", 9 AS OVERTIME_DAY, 1 AS OVERTIME_NIGHT FROM DUAL UNION
SELECT 48 AS EMPLOYEE_ID, '05/10/2014' AS "DATE", 1 AS OVERTIME_DAY, 1 AS OVERTIME_NIGHT FROM DUAL UNION
SELECT 48 AS EMPLOYEE_ID, '05/20/2014' AS "DATE", 9 AS OVERTIME_DAY, 4 AS OVERTIME_NIGHT FROM DUAL
)
SELECT
    EMPLOYEE_ID,
    CASE WHEN SUM(OVERTIME_DAY + OVERTIME_NIGHT) >= 15 THEN
      15
    ELSE
      SUM(OVERTIME_DAY + OVERTIME_NIGHT)
    END AS OVERTIME_50,

    GREATEST(0,SUM(OVERTIME_DAY + OVERTIME_NIGHT) - 15) AS OVERTIME_100

FROM DATA
GROUP BY EMPLOYEE_ID
那么我有:

Overtime 50% day: 11 hrs
Overtime 50% night: 4 hrs
Overtime 100% day: 11 hrs
Overtime 100% night: 6 hrs
我想要的结果

Employee_Id | Overtime_Day_50% | Overtime_Night_50% | Overtime_Day_100% | Overtime_Night_100% 
48          |   11 hours       |   4 hours          |   11 hrs          |    6 hrs

(行方式或列方式不重要)

对不起,如果我没有说清楚,我真的不知道是否可以只用SQL来完成这个计算

任何想法都将不胜感激。 谢谢


编辑

我有这个选择,我可以得到所有加班50%和所有加班100%,但与此我不能分开什么是白天和什么是夜间小时

Overtime 50% is all hours from 0 to 15, no matter if it's day or night:
3 hours [05/03/2014] [Day]
4 hours [05/03/2014] [Night]
8 hours [05/04/2014] [Day] (2 hours is left for this day, left hours and next hours will be 100%)
Overtime 100% is all hours above 15:
1 hours [05/04/2014] [Day]
1 hours [05/04/2014] [Night]
1 hours [05/10/2014] [Day]
1 hours [05/10/2014] [Night]
9 hours [05/20/2014] [Day]
4 hours [05/20/2014] [Night]
WITH DATA AS (           
SELECT 48 AS EMPLOYEE_ID, '05/03/2014' AS "DATE", 3 AS OVERTIME_DAY, 4 AS OVERTIME_NIGHT FROM DUAL UNION
SELECT 48 AS EMPLOYEE_ID, '05/04/2014' AS "DATE", 9 AS OVERTIME_DAY, 1 AS OVERTIME_NIGHT FROM DUAL UNION
SELECT 48 AS EMPLOYEE_ID, '05/10/2014' AS "DATE", 1 AS OVERTIME_DAY, 1 AS OVERTIME_NIGHT FROM DUAL UNION
SELECT 48 AS EMPLOYEE_ID, '05/20/2014' AS "DATE", 9 AS OVERTIME_DAY, 4 AS OVERTIME_NIGHT FROM DUAL
)
SELECT
    EMPLOYEE_ID,
    CASE WHEN SUM(OVERTIME_DAY + OVERTIME_NIGHT) >= 15 THEN
      15
    ELSE
      SUM(OVERTIME_DAY + OVERTIME_NIGHT)
    END AS OVERTIME_50,

    GREATEST(0,SUM(OVERTIME_DAY + OVERTIME_NIGHT) - 15) AS OVERTIME_100

FROM DATA
GROUP BY EMPLOYEE_ID
结果:

Employeed_Id   |   OVERTIME_50    |   OVERTIME_100
    48         |        15        |         17

如果加班时间不分白天或黑夜计算,为什么不只计算各组(白天/晚上)的预合计总数和每天的总计vs。无论如何,工资将在支付期结束时支付。我想

SELECT
      PreQry.*,
      PreQry.TotalHours,
      CASE when PreQry.TotalHours <= 15 
         then PreQry.TotalHours
         ELSE 15 end as OTAt50Pcnt,
      CASE when PreQry.TotalHours <= 15 
         then 0
         ELSE PreQry.TotalHours - 15 end as OTAt100Pcnt
   from
      ( select 
              tc.Employee_ID,
              SUM( tc.overtime_day + tc.overtime_night ) as totalHours,
              SUM( tc.overtime_day ) as totalOTDay,
              SUM( tc.overtime_night ) as totalOTNight
           from
              TimeCards tc
           group by
              tc.Employee_ID ) PreQry

我认为这是一个更可行的解决方案,但只是作为Oracle每日汇总的替代方案。我相信有更深入经验的人可能能够提供更准确的信息来满足您的要求。

以与原始数据相同的格式处理数据,即添加新列而不是新行,我们可以得到

With D AS (
  Select Employee_Id, "Date", Overtime_Day, Overtime_Night
       , SUM(Overtime_Day + Overtime_Night) 
         OVER (ORDER BY "Date") - Overtime_Night Total_Day
       , SUM(Overtime_Day + Overtime_Night) 
         OVER (ORDER BY "Date") Total_Night
  From   Data
)
SELECT Employee_Id
     , SUM(Case When Total_Day < 15 Then Overtime_Day
                When Total_Day < 15 + Overtime_Day 
                  Then Overtime_Day - (Total_Day - 15)
                Else 0 
           END) Overtime_Day_50
     , SUM(Case When Total_Night < 15 Then Overtime_Night 
                When Total_Night < 15 + Overtime_Night 
                  Then Overtime_Night - (Total_Night - 15)
                Else 0 
           END) Overtime_Night_50
     , SUM(Case When Total_Day < 15 Then 0
            When Total_Day < 15 + Overtime_Day Then Total_Day - 15
            When Total_Day > 15 Then Overtime_Day
       END) Overtime_Day_100
     , SUM(Case When Total_Night < 15 Then 0
            When Total_Night < 15 + Overtime_Night Then Total_Night - 15
            When Total_Night > 15 Then Overtime_Night
       END) Overtime_Night_100
FROM   D
GROUP BY Employee_Id
使用
%bStart%
%bEnd%
作为块的起始值和结束值,但这将不是非常灵活,使用两个以上的块时,不同的方法更好,它还允许从查询中删除幻数,以便在表中移动它们

With D AS (
  SELECT Employee_Id, "Date", Overtime_Day, Overtime_Night
       , SUM(Overtime_Day + Overtime_Night) OVER (ORDER BY "Date") 
       - (Overtime_Day + Overtime_Night) Total_Begin
       , SUM(Overtime_Day + Overtime_Night) OVER (ORDER BY "Date")
       - Overtime_Night Total_Day
       , SUM(Overtime_Day + Overtime_Night) OVER (ORDER BY "Date") Total_Night
  FROM   Data
), Block AS (
  SELECT 1 ID, 'Overtime_50' Name, 0 bStart, 15 bEnd FROM DUAL
  UNION ALL
  SELECT 2, 'Overtime_60', 15, 20 FROM DUAL
  UNION ALL 
  SELECT 3, 'Overtime_100', 20, 999 FROM DUAL
)
  SELECT Employee_Id
       , block.Name
       , SUM(CASE WHEN Total_Begin < bStart AND Total_Day > bStart THEN Total_Day - bStart
                  WHEN Total_Day < bStart THEN 0
                  WHEN Total_Day <= bEnd THEN OverTime_Day
                  WHEN Total_Begin < bEnd AND Total_Day > bEnd THEN bEnd - Total_Begin
             END) Overtime_Day
       , SUM(CASE WHEN Total_Day >= bStart AND Total_Night < bEnd THEN Overtime_Night
                  WHEN Total_Begin < bEnd AND Total_Day > bEnd THEN 0
                  WHEN Total_Day > bStart AND Total_Night > bEnd THEN bEnd - Total_Day
                  WHEN Total_Day < bStart AND Total_Night > bStart THEN Total_Night - bStart
             END) Overtime_Night
  FROM   D
         INNER JOIN Block ON
               (Total_Begin < bStart AND Total_Night > bStart)
            OR (Total_Begin >= bStart AND Total_Begin < bEnd)
GROUP BY Employee_Id, block.Name, block.ID
ORDER BY block.ID
与最初的OP输出请求稍有不同,但如果需要,从这里获得这些请求并不困难

如果希望采用单行和多列格式,只需使用
PIVOT
操作符即可

    With D AS (
  SELECT Employee_Id, "Date", Overtime_Day, Overtime_Night
       , SUM(Overtime_Day + Overtime_Night) OVER (ORDER BY "Date") 
       - (Overtime_Day + Overtime_Night) Total_Begin
       , SUM(Overtime_Day + Overtime_Night) OVER (ORDER BY "Date")
       - Overtime_Night Total_Day
       , SUM(Overtime_Day + Overtime_Night) OVER (ORDER BY "Date") Total_Night
  FROM   Data
), Block AS (
  SELECT 1 ID, 'Overtime_50' Name, 0 bStart, 15 bEnd FROM DUAL
  UNION ALL
  SELECT 2, 'Overtime_60', 15, 20 FROM DUAL
  UNION ALL 
  SELECT 3, 'Overtime_100', 20, 999 FROM DUAL
)
SELECT * FROM (
    SELECT Employee_Id
       , block.Name
       , SUM(CASE WHEN Total_Begin < bStart AND Total_Day > bStart THEN Total_Day - bStart
                  WHEN Total_Day < bStart THEN 0
                  WHEN Total_Day <= bEnd THEN OverTime_Day
                  WHEN Total_Begin < bEnd AND Total_Day > bEnd THEN bEnd - Total_Begin
             END) Overtime_Day
       , SUM(CASE WHEN Total_Day >= bStart AND Total_Night < bEnd THEN Overtime_Night
                  WHEN Total_Begin < bEnd AND Total_Day > bEnd THEN 0
                  WHEN Total_Day > bStart AND Total_Night > bEnd THEN bEnd - Total_Day
                  WHEN Total_Day < bStart AND Total_Night > bStart THEN Total_Night - bStart
             END) Overtime_Night
    FROM   D
         INNER JOIN Block ON
               (Total_Begin < bStart AND Total_Night > bStart)
            OR (Total_Begin >= bStart AND Total_Begin < bEnd)
    GROUP BY Employee_Id, block.Name, block.ID
    ORDER BY block.ID
)PIVOT (SUM(OVERTIME_DAY) AS Day, SUM(OVERTIME_NIGHT) AS Night FOR (Name) in ('Overtime_50' as Overtime_50,'Overtime_60' as Overtime_60,'Overtime_100' as Overtime_100))

是SQL Server、Oracle、MySQL还是其他一些RDBMS?您能发布当前使用的SQLL吗?除了上面的评论,考虑提供适当的DDL(和/或SQLFIDLE)和期望的结果集。问题第三代码块:注释4行不清楚。8+4+3=15,其中2小时从何处开始?2003年5月和2004年5月的总和是多少?日期一点都不重要?事实上,我正在使用Oracle,但我在问题中标记了其他RDBMS,只是为了从所有RDBMS中获得任何想法,以便我以后可以将其转换为Oracle。如果我不需要从O/T 50%和O/T 100%中区分什么是白天小时,什么是夜间小时,我就可以使用它。通过从数据中以升序手动求和,我知道值如下:加班50%天:11小时,加班50%夜:4小时,加班100%天:11小时,加班100%夜:6小时。但我还不知道如何在这个选择中把它放在逻辑上。谢谢你的回答:)嘿,塞皮顿,谢谢你的回答:)它起了很大的作用。但我仍在分析你的逻辑,我有一个问题。在这段代码中,它总是“优先”安排白天的时间(好像白天的时间比晚上的时间来得早)。如果我把“加班之夜”的减法去掉,把“加班之日”的减法放到“加班之夜”的减法里,我会把晚上的事情安排得优先吗?我明白了。非常感谢。我仍然在尝试做一些改变,比如在两个范围之间增加一个加班范围(60%),但是我遇到了一些问题。你能帮我找钱吗?新的范围是:加班50%:从0到15,加班60%:从16到20,加班100%:>20。谢谢你的帮助,伙计!我会继续我的尝试。这肯定比我尝试的要好。再次感谢你。我做了一点小小的更改,只是将行交换到列,因为我需要它们采用单行和多列格式。所以我用这种方法编辑了你的评论,希望你不介意。
Employee_Id | Overtime_50_Day | Overtime_50_Night | Overtime_60_Day | Overtime_60_Night | Overtime_100_Day | Overtime_100_Night
         48 |              11 |                4  |               2 |                 3 |                9 |                  5