我有一个包含两列的列。一个是TIMESTAMP
,另一个是DIGITAL_BIT
。
值数字位可以是0或1,并在白天更改几次。一天中的每一分钟都存储在此表中。我需要以某种方式阅读一天这个值从0变为1的次数。
是否可以创建一个返回此更改计数的查询?我的想法是这样的:
select * from mytable where digital_bit = 1 and digital_bit (of previous row) = 0 order by timestamp
这可以通过查询完成,还是我必须处理程序中的所有数据?
由于
样品
timestamp | digital_bit
100000 | 0
100001 | 0
100002 | 1
100003 | 1
100004 | 0
100005 | 1
100006 | 0
100007 | 0
100008 | 1
以上应该返回3,因为数字值从0传递到1的3倍。我需要计算数字值从0变为1的频率。
答案 0 :(得分:3)
你走了。这将使您计算digital_bit从0切换到1的次数(在您的示例中,这将返回3)。
SELECT COUNT(*)
FROM mytable curr
WHERE curr.digital_bit = 1
AND (
SELECT digital_bit
FROM mytable prev
WHERE prev.timestamp < curr.timestamp
ORDER BY timestamp DESC
LIMIT 1
) = 0
(原始答案依赖于顺序的时间戳:例如,没有从100001跳转到100003.答案现在已经更新,没有限制。)
答案 1 :(得分:1)
这对于大量数据来说不太可能有效,但是您可以获取所有行并计算它们的序列号,然后再次执行相同操作,但序列号偏移1.然后加入2这些计算出的序列号匹配但是第一个的数字位为0而另一个的数字位为1: -
SELECT COUNT(*)
FROM
(
SELECT mytable.timestamp, mytable.digital_bit, @aCount1:=@aCount1+1 AS SeqCount
FROM mytable
CROSS JOIN (SELECT @aCount1:=1) sub1
ORDER BY timestamp
) a
INNER JOIN
(
SELECT mytable.timestamp, mytable.digital_bit, @aCount2:=@aCount2+1 AS SeqCount
FROM mytable
CROSS JOIN (SELECT @aCount2:=0) sub1
ORDER BY timestamp
) b
ON a.SeqCount = b.SeqCount
AND a.digital_bit = 0
AND b.digital_bit = 1
编辑 - 替代解决方案,我很想知道这是如何表现的。它避免了添加序列号的需要,也避免了相关的子查询: -
SELECT COUNT(*)
FROM
(
SELECT curr.timestamp, MAX(curr2.timestamp) AS MaxTimeStamp
FROM mytable curr
INNER JOIN mytable curr2
ON curr.timestamp > curr2.timestamp
AND curr.digital_bit = 1
GROUP BY curr.timestamp
) Sub1
INNER JOIN mytable curr
ON Sub1.MaxTimeStamp = curr.timestamp
AND curr.digital_bit = 0
答案 2 :(得分:1)
改编自:How do I query distinct values within multiple sub record sets
select count(*)
from (select t1.*,
(select digital_bit
from table t2
where t2.timestamp < t1.timestamp
order by timestamp desc LIMIT 1
) as prevvalue
from table t1
) t1
where prevvalue <> digital_bit and digital_bit = 1;
答案 3 :(得分:1)
如果每分钟有一次结果,你可以简单地将表连接到自己,并且 使用timestamp + 1以及leftbit!= rightbit作为连接条件。
http://sqlfiddle.com/#!8/791c0/6
所有变更:
SELECT
COUNT(*)
FROM
test a
INNER JOIN
test b
ON
a.digital_bit != b.digital_bit
AND b.timestamp = a.timestamp+1;
从0变为1
SELECT
COUNT(*)
FROM
test a
INNER JOIN
test b
ON
a.digital_bit = 0 AND
a.digital_bit != b.digital_bit
AND b.timestamp = a.timestamp+1;
从1更改为0
SELECT
COUNT(*)
FROM
test a
INNER JOIN
test b
ON
a.digital_bit = 1 AND
a.digital_bit != b.digital_bit
AND b.timestamp = a.timestamp+1;
答案 4 :(得分:0)
据我所知,你每分钟都有一个查询。所以你对性能没有任何问题。
您可以添加标记:
timestamp | digital_bit | changed
100000 | 0 | 0
100001 | 0 | 0
100002 | 1 | 1
100003 | 1 | 0
100004 | 0 | 1
100005 | 1 | 1
100006 | 0 | 1
100007 | 0 | 0
100008 | 1 | 1
在插入之前进行检查:
SELECT digital_bit
FROM table
ORDER BY timestamp DESC
LIMIT 1
如果digital_bit
不同,请插入带有标记的新行。
然后你就可以拿COUNT
个旗帜:
SELECT COUNT(*)
FROM table
WHERE DATE BETWEEN (start, end)
AND changed = 1
希望能在答案中看到更好的解决方案。