使用 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.01
和0.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 位置执行此操作,并汇总一个日期范围内的所有值。您建议的方式似乎不仅查询速度更快,而且更清晰。
我有 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.01
和0.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 位置执行此操作,并汇总一个日期范围内的所有值。您建议的方式似乎不仅查询速度更快,而且更清晰。