我有一个包含三列的MySQL表:takenOn (datetime - primary key)
,sleepDay (date)
和type (int)
。这张表包含了从睡觉到起床的睡眠数据(每隔一段时间)。
例如,如果我在10月29日晚上11点睡觉并于10月30日早上6点起床,我将有420条记录(7小时* 60分钟)。 takenOn
的范围是2016-10-29 23:00:00
到2016-10-30 06:00:00
。所有420条记录的sleepDay
为2016-10-30
。 type
是"质量"我的睡眠(1 =睡着,2 =不安,3 =清醒)。我试图得到多少次我不安/清醒,这可以通过计算我看到type = 2(或type = 3)连续多少次来计算
到目前为止,我必须遵循查询,该查询仅适用于一天。这是正确的"有效的"这样做的方法(因为这种方法要求我在takenOn
)中没有任何"间隙"的数据?另外,如何展开它以计算所有可能的sleepDays
?
SELECT
sleepDay,
SUM(CASE WHEN type = 2 THEN 1 ELSE 0 END) AS TimesRestless,
SUM(CASE WHEN type = 3 THEN 1 ELSE 0 END) AS TimesAwake
FROM
(SELECT s1.sleepDay, s1.type
FROM sleep s1
LEFT JOIN sleep s2
ON s2.takenOn = ADDTIME(s1.takenOn, '00:01:00')
WHERE
(s2.type <> s1.type OR s2.takenOn IS NULL)
AND s1.sleepDay = '2016-10-30'
ORDER BY s1.takenOn) a
我创建了一个SQL小提琴 - http://sqlfiddle.com/#!9/b33b4/3
谢谢!
答案 0 :(得分:1)
考虑到你所知道的假设,你自己的解决方案非常好。
我在这里提出了一个替代解决方案,它可以很好地处理系列中的差距,并且可以一次使用超过一天。
缺点是它更依赖于非标准的MySql功能(内联使用变量):
select sleepDay,
sum(type = 2) TimesRestless,
sum(type = 3) TimesAwake
from (
select @lagDay as lagDay,
@lagType as lagType,
@lagDay := sleepDay as sleepDay,
@lagType := type as type
from (select * from sleep order by takenOn) s1,
(select @lagDay := '',
@lagType := '') init
) s2
where lagDay <> sleepDay
or lagType <> type
group by sleepDay
要了解它是如何工作的,它可以帮助自己选择第二个select
语句。最内层select
必须有order by
子句,以确保中间查询将按顺序处理记录,这对于那里发生的变量赋值很重要。
查看更新后的SQL fiddle。