所以我有以下结构:
+------+---------------+---------------+----+
| guid | current_level | current_value | pk |
+------+---------------+---------------+----+
| a | 100 | 12 | 1 |
| a | 200 | 12 | 2 |
| a | 200 | 12 | 3 |
| a | 200 | 12 | 4 |
| a | 200 | 12 | 6 |
| a | 300 | 14 | 7 |
| a | 300 | 12 | 9 |
| a | 300 | 12 | 10 |
| a | 300 | 14 | 12 |
| b | 100 | 10 | 5 |
| b | 100 | 10 | 8 |
| b | 200 | 12 | 11 |
| b | 200 | 12 | 13 |
+------+---------------+---------------+----+
我希望计算a和b非连续地达到200级的次数(300次,但现在只有200次) 即我期待的结果:
+------+-------+-------+
| guid | level | times |
+------+-------+-------+
| a | 200 | 1 |
| b | 200 | 1 |
+------+-------+-------+
(我不能做到独特,因为200s的单独条纹应分开计算)
当我执行以下操作时:
set @id = "none";
set @lev = 10; -- arbitary non zero starting level
SELECT guid, current_level , if(@id <> guid, @lev := 10, 0) AS useless, case when @id <> guid then @id := guid else 0 end AS useless2
, (case when (current_level = 200 AND current_level <> @lev) then 1 else 0 end) as TIMES
, if(current_level = 200 AND current_level <> @lev, @lev := current_level, 0) AS useless3
FROM (SELECT * FROM sensor_logs order by guid) as T
我明白了:
+------+---------------+---------+----------+----------+----------+
| guid | current_level | useless | useless2 | TIMES | useless3 |
+------+---------------+---------+----------+----------+----------+
| a | 100 | 10 | a | 0 | 0 |
| a | 200 | 0 | 0 | 1 | 200 |
| a | 200 | 0 | 0 | 0 | 0 |
| a | 200 | 0 | 0 | 0 | 0 |
| a | 200 | 0 | 0 | 0 | 0 |
| a | 300 | 0 | 0 | 0 | 0 |
| a | 300 | 0 | 0 | 0 | 0 |
| a | 300 | 0 | 0 | 0 | 0 |
| a | 300 | 0 | 0 | 0 | 0 |
| b | 100 | 10 | b | 0 | 0 |
| b | 100 | 0 | 0 | 0 | 0 |
| b | 200 | 0 | 0 | 1 | 200 |
| b | 200 | 0 | 0 | 0 | 0 |
+------+---------------+---------+----------+----------+----------+
所以现在总结TIMES
列并按guid
分组应该可以解决问题,即:
set @id = "none";
set @lev = 10; -- arbitary non zero starting level
SELECT guid, current_level , if(@id <> guid, @lev := 10, 0) AS useless, case when @id <> guid then @id := guid else 0 end AS useless2
, sum(case when (current_level = 200 AND current_level <> @lev) then 1 else 0 end) as TIMES
, if(current_level = 200 AND current_level <> @lev, @lev := current_level, 0) AS useless3
FROM (SELECT * FROM sensor_logs order by guid) as T
GROUP BY guid
但我得到以下内容:
+------+---------------+---------+----------+----------+----------+
| guid | current_level | useless | useless2 | TIMES | useless3 |
+------+---------------+---------+----------+----------+----------+
| a | 100 | 10 | a | 4 | 0 |
| b | 100 | 10 | b | 2 | 0 |
+------+---------------+---------+----------+----------+----------+
我不明白为什么总结一个有两个1的列(每个guid一个)导致4和2。
我做错了吗?或者更多地与查询(和求和函数)如何执行的基础机制有关?
答案 0 :(得分:1)
您的第一个查询最好这样写:
SELECT guid, current_level , if(@id <> guid, @lev := 10, 0) AS useless, case when @id <> guid then @id := guid else 0 end AS useless2
, (case when (current_level = 200 AND current_level <> @lev) then 1 else 0 end) as TIMES
, if(current_level = 200 AND current_level <> @lev, @lev := current_level, 0) AS useless3
FROM sensor_logs
, (SELECT @id := 'none', @lev := 10) var_init_subquery
ORDER BY guid
在需要时,不仅在子查询中明确地进行排序不仅更加干净,在子查询中执行它也可能导致错误的执行计划(这意味着在临时表的情况下性能不佳)。
对于最终结果,您不应该直接应用GROUP BY等。 SELECT(以及因此您的变量和计算)在
SELECT guid, SUM(times) FROM (
SELECT guid, current_level , if(@id <> guid, @lev := 10, 0) AS useless, case when @id <> guid then @id := guid else 0 end AS useless2
, (case when (current_level = 200 AND current_level <> @lev) then 1 else 0 end) as TIMES
, if(current_level = 200 AND current_level <> @lev, @lev := current_level, 0) AS useless3
FROM sensor_logs
, (SELECT @id := 'none', @lev := 10) var_init_subquery
ORDER BY guid
) sq
GROUP BY guid