【发布时间】:2014-05-12 12:31:21
【问题描述】:
我一直在研究其他几个 SO 问题,但我无法从中找出解决方案。首先,描述,然后是我从其他线程中丢失的内容。 (请注意:我非常了解我们数据库的非标准化结构,这是我之前在会议上讨论过的问题,但这是我们所拥有的,也是我必须使用的。)
背景说明
我们有一台可以在 25 个位置生产产品的机器。这些产品的生产数据被记录在一个表格中,其中记录了每个位置的电流和电压。这仅在机器实际生产产品(即机器中有产品)时记录。没有产品存在的时间,没有记录任何内容。
这台机器可以运行在两种不同的生产模式:全面生产和研发生产。全面生产意味着连续插入产品,以便每个实例始终都有一个产品(即机器中始终存在 25 个产品)。第二种模式,研发生产,一次只生产一个产品(即一个产品进入机器,一个一个地经过25个实例,当这个完成后,第二个产品进入机器)。
澄清一下:当产品出现时,每个职位每秒都会记录一次数据,这意味着在全面生产运行时每秒记录 25 个实例。当 R&D 模式运行时,位置 1 将有 ~20 个实例持续 20 秒,位置 2 将有 ~20 个实例持续接下来的 20 秒,依此类推。
表结构
生产数据:
- id(自动增量)
- 产品ID
- 位置
- 时间(记录数据的时间戳)
- 电流(安培)
- 电压(伏特)
问题
我们想计算机器的正常运行时间,但是我们想将生产模式和研发模式的正常运行时间分开,并且我们想每周分开这个数据。
猜测的解决方案
由于我们每秒记录一次实例,因此我可以计算表中时间值的 DISTINCT 实例的数量,以找出生产和研发模式的总正常运行时间。为了找到研发模式,我可以肯定地说,只要有一个只有一个条目的时间实例,我就在研发模式下运行(生产模式将有 25 个实例)。
目前的进展
我有以下查询,它总结了所有不同的实例以找到生产和研发模式:
SELECT YEARWEEK(time) AS YWeek, COUNT(DISTINCT time) AS Time_Seconds, ROUND(COUNT(DISTINCT time)/3600, 1) AS Time_Hours
FROM Database.productiondata
WHERE YEARWEEK(time) >= YEARWEEK(curdate()) - 21
GROUP BY YWeek;
此查询找出表中有多少 DISTINCT 时间实例,并按周计算数量和组。
问题
上面的查询计算了表中存在的实例数量,但我只想找到唯一的实例。基本上,我试图找到类似 IF count(time) = 1 的东西,然后计算那个实例,IF count(time) > 1 然后根本不计算它(DISTINCT 仍然计算这个)。
我查看了其他几个 SO 线程,但几乎都解释了如何使用 DISTINCT 查找唯一值,它只完成了我正在寻找的一半。我得到的最接近的是this,它使用了 HAVING 子句。我目前陷入以下困境:
SELECT YEARWEEK(time) as YWeek, COUNT(Distinct time) As Time_Seconds, ROUND(COUNT(Distinct time)/3600, 1) As Time_Hours
FROM
(SELECT * FROM Database.productiondata
WHERE time > '2014-01-01 00:00:00'
GROUP BY time
HAVING count(time) = 1) as temptime
GROUP BY YWeek
ORDER BY YWeek;
这里的问题是我们在嵌套的 select 子句中有一个 GROUP BY 时间,它需要永远(今年只有大约 500 万行,所以我可以理解)。我的意思是,从语法上讲,我认为这是正确的,但执行起来需要很长时间。甚至解释这个超时。
这就是我所在的地方。这是正确的方法还是有其他更智能/需要更少查询时间/避免按时间分组的方法?
编辑:作为示例,我们有这个表格(对于格式化道歉,不知道如何在 SO 上制作表格格式)
id position time
1 1 1
2 2 1
3 5 1
4 19 1
... ... ...
25 7 1
26 3 2
27 6 2
... ... ...
此表显示了在进行生产运行时的样子。如您所见,在将数据记录到表中时,没有哪个位置获得第一个条目的通用结构;发生的情况是每秒记录 25 个位置,然后根据 PLC 为每个位置发送数据的速度将数据添加到表中。下表显示了该表在研究模式下运行时的外观。
id position time
245 1 1
246 1 2
247 1 3
... ... ...
269 1 25
270 2 26
271 2 27
... ... ...
由于所有数据都合并到一个表中,我们想找出当 COUNT(time) 正好等于 1 时有多少实例,或者我们可以在 COUNT(time) 严格大于时查找每个实例大于 1。
EDIT2:作为对 Alan 的回复,建议给了我
YWeek Time_Seconds Time_Hours
201352 1 0.0
201352 1 0.0
201352 1 0.0
... ... ...
201352 1 0.0 (1000 row limit)
而我想要的输出是
Yweek Time_Seconds Time_Hours
201352 2146 35.8
201401 5789 96.5
... ... ...
201419 8924 148.7
EDIT3:到目前为止,我已经收集了尝试和结果here,并在查询上方以灰色显示。
【问题讨论】:
-
我很困惑。我看不到这里面的“正常化”缺陷!?!?
-
我添加了该评论作为预防措施,因为我之前在这里用类似结构提出的问题说“为什么你没有一个单独的表格,其中包含位置?为什么它们在同一个表格中?”等等:)
-
请看我更新的答案。
-
感谢您的更新,我在下面回复了其他信息。
标签: mysql sql mysql-workbench