使用 max() 的具体方法

a specific way to use max()

我有 DateTime、total、material 和 Mix 列。

此设备 运行s 混合 A x 小时数,然后切换到混合 B x 小时数。然后切换回 Mix A。

我想要一个查询:

Select max(total), material, mix 
from database 
group by material, mix

但是我需要了解 Mix A 是 运行 两次并且只会记录 1 个值的事实,我不知道在那个中使用了多少 material跳过。

有没有办法查看 Max(总计),然后在每次混合或 material 变化时寻找新的最大值? (不是实际不同的混音/material,而是当它实际上从混音 B 变为混音 A 时。

编辑以显示数据的样子

Timestamp                  Mix           Material          Tons  
2017-02-08 07:49:25.000    MixA          Mat1              30.05
2017-02-08 07:50:25.000    MixA          Mat1              30.27
2017-02-08 07:51:25.000    MixA          Mat1              30.50
2017-02-08 07:52:25.000    MixA          Mat1              30.76
2017-02-08 07:53:25.000    MixA          Mat1              31.01
2017-02-08 07:58:25.000    MixB          Mat1              0.1
2017-02-08 07:59:25.000    MixB          Mat1              0.8
2017-02-08 08:00:25.000    MixB          Mat1              1.3
2017-02-08 08:01:25.000    MixB          Mat1              2.0
2017-02-08 08:02:25.000    MixB          Mat1              2.5
2017-02-08 08:10:25.000    MixA          Mat1              0.1
2017-02-08 08:01:25.000    MixA          Mat1              0.5

因此,在上面显示的第一条记录之前,机器 运行ning 了一段时间。然后他们切换混音,运行,然后切换回去并结束当天的制作。

我正在尝试找到最有效的方法来查找使用的 material 量,因为吨数列是一个 运行 宁总计,我不能只对它求和。 MAX() 真的很简单,但是我会错过 Mix A.

的第二个 运行

我觉得 gap-and-islands

示例数据

注意,我添加了 Mat2 以表明我们需要按它进行分区并固定最后一个条目的时间戳。

DECLARE @T TABLE(ts datetime2(0), Mix varchar(50), Material varchar(50), Tons float);

INSERT INTO @T (ts, Mix, Material, Tons) VALUES
('2017-02-08 07:49:25', 'MixA', 'Mat1', 30.05),
('2017-02-08 07:50:25', 'MixA', 'Mat1', 30.27),
('2017-02-08 07:51:25', 'MixA', 'Mat1', 30.50),
('2017-02-08 07:52:25', 'MixA', 'Mat1', 30.76),
('2017-02-08 07:53:25', 'MixA', 'Mat1', 31.01),
('2017-02-08 07:58:25', 'MixB', 'Mat1', 0.1  ),
('2017-02-08 07:59:25', 'MixB', 'Mat1', 0.8  ),
('2017-02-08 08:00:25', 'MixB', 'Mat1', 1.3  ),
('2017-02-08 08:01:25', 'MixB', 'Mat1', 2.0  ),
('2017-02-08 08:02:25', 'MixB', 'Mat1', 2.5  ),
('2017-02-08 08:10:25', 'MixA', 'Mat1', 0.1  ),
('2017-02-08 08:11:25', 'MixA', 'Mat1', 0.5  ),
('2017-02-08 07:49:25', 'MixA', 'Mat2', 30.05),
('2017-02-08 07:50:25', 'MixA', 'Mat2', 30.27),
('2017-02-08 07:51:25', 'MixA', 'Mat2', 30.50),
('2017-02-08 07:52:25', 'MixA', 'Mat2', 30.76),
('2017-02-08 07:53:25', 'MixA', 'Mat2', 31.01),
('2017-02-08 07:58:25', 'MixB', 'Mat2', 0.1  ),
('2017-02-08 07:59:25', 'MixB', 'Mat2', 0.8  ),
('2017-02-08 08:00:25', 'MixB', 'Mat2', 1.3  ),
('2017-02-08 08:01:25', 'MixB', 'Mat2', 2.0  ),
('2017-02-08 08:02:25', 'MixB', 'Mat2', 2.5  ),
('2017-02-08 08:10:25', 'MixA', 'Mat2', 0.1  ),
('2017-02-08 08:11:25', 'MixA', 'Mat2', 0.5  );

查询

WITH
CTE_rn
AS
(
    SELECT
        ts
        ,Mix
        ,Material
        ,Tons
        ,ROW_NUMBER() OVER (PARTITION BY Material ORDER BY ts) AS rn1
        ,ROW_NUMBER() OVER (PARTITION BY Material, Mix ORDER BY ts) AS rn2
    FROM @T
)
,CTE_Groups
AS
(
    SELECT
        ts
        ,Mix
        ,Material
        ,Tons
        ,rn1
        ,rn2
        ,rn1 - rn2 AS GroupNumber
    FROM CTE_rn
)
SELECT
    Material
    ,Mix
    ,MAX(Tons) AS MaxTons
    ,MAX(ts) AS MaxTS
FROM CTE_Groups
GROUP BY
    Material
    ,GroupNumber
    ,Mix
ORDER BY
    Material
    ,MaxTS
;

结果

+----------+------+---------+---------------------+
| Material | Mix  | MaxTons |        MaxTS        |
+----------+------+---------+---------------------+
| Mat1     | MixA | 31.01   | 2017-02-08 07:53:25 |
| Mat1     | MixB | 2.5     | 2017-02-08 08:02:25 |
| Mat1     | MixA | 0.5     | 2017-02-08 08:11:25 |
| Mat2     | MixA | 31.01   | 2017-02-08 07:53:25 |
| Mat2     | MixB | 2.5     | 2017-02-08 08:02:25 |
| Mat2     | MixA | 0.5     | 2017-02-08 08:11:25 |
+----------+------+---------+---------------------+

如果需要,可以进一步总结为Mat1添加31.010.5。再加一个 GROUP BY Material, Mix。问题不是很清楚结果应该是什么。

工作原理

运行 查询 step-by-step,cte-by-cte 以了解其工作原理。

"Gaps and islands"是一道经典题。当 Mix 更改时,"island" 后跟 "gap"。

CTE_rn 计算两组行号。它们之间的区别是组数(CTE_Groups).

WITH
...
SELECT *
FROM CTE_Groups
ORDER BY Material, ts;

生产

+---------------------+------+----------+-------+-----+-----+-------------+
|         ts          | Mix  | Material | Tons  | rn1 | rn2 | GroupNumber |
+---------------------+------+----------+-------+-----+-----+-------------+
| 2017-02-08 07:49:25 | MixA | Mat1     | 30.05 |   1 |   1 |           0 |
| 2017-02-08 07:50:25 | MixA | Mat1     | 30.27 |   2 |   2 |           0 |
| 2017-02-08 07:51:25 | MixA | Mat1     | 30.5  |   3 |   3 |           0 |
| 2017-02-08 07:52:25 | MixA | Mat1     | 30.76 |   4 |   4 |           0 |
| 2017-02-08 07:53:25 | MixA | Mat1     | 31.01 |   5 |   5 |           0 |
| 2017-02-08 07:58:25 | MixB | Mat1     | 0.1   |   6 |   1 |           5 |
| 2017-02-08 07:59:25 | MixB | Mat1     | 0.8   |   7 |   2 |           5 |
| 2017-02-08 08:00:25 | MixB | Mat1     | 1.3   |   8 |   3 |           5 |
| 2017-02-08 08:01:25 | MixB | Mat1     | 2     |   9 |   4 |           5 |
| 2017-02-08 08:02:25 | MixB | Mat1     | 2.5   |  10 |   5 |           5 |
| 2017-02-08 08:10:25 | MixA | Mat1     | 0.1   |  11 |   6 |           5 |
| 2017-02-08 08:11:25 | MixA | Mat1     | 0.5   |  12 |   7 |           5 |
| 2017-02-08 07:49:25 | MixA | Mat2     | 30.05 |   1 |   1 |           0 |
| 2017-02-08 07:50:25 | MixA | Mat2     | 30.27 |   2 |   2 |           0 |
| 2017-02-08 07:51:25 | MixA | Mat2     | 30.5  |   3 |   3 |           0 |
| 2017-02-08 07:52:25 | MixA | Mat2     | 30.76 |   4 |   4 |           0 |
| 2017-02-08 07:53:25 | MixA | Mat2     | 31.01 |   5 |   5 |           0 |
| 2017-02-08 07:58:25 | MixB | Mat2     | 0.1   |   6 |   1 |           5 |
| 2017-02-08 07:59:25 | MixB | Mat2     | 0.8   |   7 |   2 |           5 |
| 2017-02-08 08:00:25 | MixB | Mat2     | 1.3   |   8 |   3 |           5 |
| 2017-02-08 08:01:25 | MixB | Mat2     | 2     |   9 |   4 |           5 |
| 2017-02-08 08:02:25 | MixB | Mat2     | 2.5   |  10 |   5 |           5 |
| 2017-02-08 08:10:25 | MixA | Mat2     | 0.1   |  11 |   6 |           5 |
| 2017-02-08 08:11:25 | MixA | Mat2     | 0.5   |  12 |   7 |           5 |
+---------------------+------+----------+-------+-----+-----+-------------+

然后我们简单GROUP BY Material, GroupNumber, Mix得到最终结果

将它放在这里只是为了展示正在使用的内容,以便您了解您帮助清理和优化了多少。 目前的做法是:

SELECT D1.[Day],
  D1.[TimeStamp],
  D1.[Material],
  D1.Source,
  CASE WHEN D1.[RunTotal] - D2.[RunTotal] >= 0 
    THEN D1.[RunTotal] - D2.[RunTotal] ELSE 0 END AS [Tons]
FROM (SELECT ROW_NUMBER() OVER (ORDER BY [TimeStamp]) rownum, 
  [TimeStamp], 
  cast([TimeStamp] AS date) [Day], 
  MIN(CASE Equipment WHEN 'Bin1' THEN CAST([Run Total] AS decimal(18, 3)) END) AS [RunTotal], 
  MIN(CASE Equipment WHEN 'Bin1' THEN Material END) AS [Material], 
  'Bin1' AS Source
FROM  Plant_Production.dbo.Data  
WHERE Equipment = 'Bin1'
GROUP BY [Timestamp]) D1 LEFT OUTER JOIN
  (SELECT ROW_NUMBER() OVER (ORDER BY [TimeStamp]) rownum, 
    [TimeStamp],     
    cast([TimeStamp] AS date) [Day], 
    MIN(CASE Equipment WHEN 'Bin1' THEN CAST([Run Total] AS decimal(18, 3)) END) AS [RunTotal],
    MIN(CASE Equipment WHEN 'Bin1' THEN [Material] END) AS [Material], 
    'Bin1' AS Source
  FROM Plant_Production.dbo.Data
  WHERE Equipment = 'Bin1'
  GROUP BY [TimeStamp]) D2 ON D1.RowNum - 1 = D2.RowNum AND D1.[Day] = D2.[Day]

他们对每个 Bin 位置执行此操作,并汇总一个日期范围内的所有值。您建议的方式似乎不仅查询速度更快,而且更清晰。