【问题标题】:Sql Server Shift Report with 4 shiftSql Server 班次报告与 4 班
【发布时间】:2018-09-14 06:11:48
【问题描述】:

我有一个包含电力消耗数据的 SQL 表。 现有列:日期、名称和值。这是一个示例:

    DT                      Tag                           Value

2018-09-13 17:09:32.553 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-13 18:09:32.557 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-13 19:09:32.567 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-13 20:09:32.580 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-13 21:09:32.583 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-13 22:09:32.593 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-13 23:09:32.597 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 00:09:32.603 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 01:09:32.603 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 02:09:32.603 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 03:09:32.610 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 04:09:32.627 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 05:09:32.640 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 06:09:32.643 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 07:09:32.650 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 08:09:32.663 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 09:09:32.677 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 10:09:32.677 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 11:09:32.677 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125
2018-09-14 12:09:32.680 Siemens.MDBPLC.elDCS2.elDCS2p   30559.01953125

每小时都会向表中插入值。

我需要创建轮班报告,我们可以在其中按轮班小时数的平均值查看哪个班次消耗的能源。 我们有 4 个班次:

2019-09-13 07:00-19:00 A
2019-09-13 19:00-07:00 B
 2019-09-14 07:00-19:00 C
2019-09-14 19:00-07:00 D

因此我需要这样的输出:

Date               Shift  Value
2019-09-13 07:00     A     30559.01953125
2019-09-13 19:00     B     30559.01953125
2019-09-14 07:00     C     30559.01953125

他们使用 MS SQL 2012。不能改变结构或任何东西,只能从数据库中选择数据。

【问题讨论】:

  • 请提供样本数据预期结果。当你这样做时,你会得到更快、更准确的答案
  • 您似乎每天只有 2 个 12 小时轮班。为什么称这为“四班倒”?
  • 因为在我们工厂我们有 4 班 2 天 - A B C D,这就是为什么班次报告应该涵盖所有 4 班
  • 在您的输出中,Value 是每班所有每小时样本的 MIN、MAX 还是 AVG?
  • 您如何决定何时从“A”开始?这有关系吗?

标签: sql-server datetime group-by


【解决方案1】:

下面我选择使用 2 个交叉应用运算符形成 4 个轮班循环,以便可以重复使用列别名,希望它更易于阅读。

使用 datediff(hour,...) 和从 2018-01-01 07:00 开始的模数,我们可以计算出第一个或第二个班次中的哪些小时,然后第二个模数计算告诉我们哪个2 天是相关的,然后我们可以一起制作跨越 2 天的 4 个轮班周期。

select
     ca2.shift_start
   , ca2.shift
   , avg(value) avg_value
from table1
cross apply (
    select
           datediff(hour,'20180101 07:00', dt) % 24 hr
        , (datediff(hour,'20180101 07:00', dt) / 24) % 2 dy
    ) ca1
cross apply (
   select case
          when ca1.dy = 0 and ca1.hr between 0  and 11 then 'a'
          when ca1.dy = 0 and ca1.hr between 12 and 23 then 'b'
          when ca1.dy = 1 and ca1.hr between 0  and 11 then 'c'
          when ca1.dy = 1 and ca1.hr between 12 and 23 then 'd'
          end as shift
        , convert(varchar(13),dateadd(hour,-(case when hr < 12 then hr else hr-12 end),dt),121) shift_start
    ) ca2
group by
     ca2.shift_start
   , ca2.shift
order by
     ca2.shift_start
   , ca2.shift


+----+---------------+-------+----------------+
|    |  shift_start  | shift |   avg_value    |
+----+---------------+-------+----------------+
|  1 | 2018-09-13 07 | c     | 30559,01953125 |
|  2 | 2018-09-13 19 | d     | 30559,01953125 |
|  3 | 2018-09-14 07 | a     | 30559,01953125 |
+----+---------------+-------+----------------+

见:http://rextester.com/VHQK56298

【讨论】:

    【解决方案2】:

    您有定义班次的表格吗?在这里,我假设您有一个,并且在班次中定义的日期范围与您的示例数据匹配(2018 年)

    ;with  
    shift_table as
    (
        select shift_start = '2018-09-13 07:00', shift_end = '2018-09-13 19:00', shift = 'A'    union all
        select shift_start = '2018-09-13 19:00', shift_end = '2018-09-14 07:00', shift = 'B'    union all
        select shift_start = '2018-09-14 07:00', shift_end = '2018-09-14 19:00', shift = 'C'    union all
        select shift_start = '2018-09-14 19:00', shift_end = '2018-09-15 07:00', shift = 'D'
    )
    SELECT  s.shift_start, s.shift, Value = avg(t.Value)
    FROM    sample_table t
            inner join shift_table s    on  t.DT    >= s.shift_start
                                       and  t.DT    <  s.shift_end
    group by s.shift_start, s.shift 
    

    【讨论】:

    • 我没有换桌。我可以在 SQL 中自动生成此表吗?
    • 是的。你可以。在我的查询中,我使用cte 来定义班次数据。您只需使用所需的日期即可完成
    猜你喜欢
    • 2011-09-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 2015-03-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多