我有来自测量活动水平的加速度计的数据 - 输出是以站立或躺着的每分钟的秒数给出的(参见下表,来自1个人的例子)。
**Date** **Time** **Standing** **Lying**
21/02/2017 10:15:00 0 60
21/02/2017 10:16:00 0 60
21/02/2017 10:17:00 0 60
21/02/2017 10:18:00 0 60
21/02/2017 10:19:00 0 60
21/02/2017 10:20:00 0 60
21/02/2017 10:21:00 43 17
21/02/2017 10:22:00 60 0
21/02/2017 10:23:00 60 0
21/02/2017 10:24:00 46 14
21/02/2017 10:25:00 0 60
21/02/2017 10:26:00 0 60
21/02/2017 10:27:00 0 60
21/02/2017 10:28:00 0 60
21/02/2017 10:29:00 0 60
21/02/2017 10:30:00 0 60
21/02/2017 10:31:00 0 60
21/02/2017 10:32:00 0 60
我对每个人每天的活动变化感兴趣。因此,有兴趣计算患者在24小时内从躺卧变为站立的次数 - 例如一段时间的谎言在24小时内发生了多少次 - 但是包括60秒的阈值。例如,如果数据从平躺变为静止只有几秒钟,则可能是假的。
我有兴趣做的第二件事是计算每个(真实)说谎的平均时间,同样在每个人的24小时内计算。
SQL Server中每种方法的最佳方法是什么?
修改
以上问题过于宽泛。我想知道最好的方法来计算躺卧的总次数和平均躺卧时间 - 都是在24小时内
过渡将是从谎言变为站立的任何事物(例如桌子上的10:21:00)或反向 - 站立到谎言(例如10:24:00)
Date Bouts AvBoutTime
21/2 41 20
22/2 38 25
23/2 48 17
答案 0 :(得分:1)
我在这里只有一个部分答案,但是如果有帮助我会发布它,如果我有其他想法,我可能会调查它。
这是我所拥有的以及SQL小提琴的链接: http://sqlfiddle.com/#!18/72532/27/0
表格结构
CREATE TABLE Activity (
[Date] varchar(10),
[Time] varchar(8),
[Standing] Integer,
[Lying] Integer
);
INSERT INTO Activity ([Date], [Time], [Standing], [Lying])
VALUES
('21/02/2017', '10:15:00', 0, 60),
('21/02/2017', '10:16:00', 0, 60),
('21/02/2017', '10:17:00', 0, 60),
('21/02/2017', '10:18:00', 0, 60),
('21/02/2017', '10:19:00', 0, 60),
('21/02/2017', '10:20:00', 0, 60),
('21/02/2017', '10:21:00', 43, 17),
('21/02/2017', '10:22:00', 60, 0),
('21/02/2017', '10:23:00', 60, 0),
('21/02/2017', '10:24:00', 46, 14),
('21/02/2017', '10:25:00', 0, 60),
('21/02/2017', '10:26:00', 0, 60),
('21/02/2017', '10:27:00', 0, 60),
('21/02/2017', '10:28:00', 0, 60),
('21/02/2017', '10:29:00', 0, 60),
('21/02/2017', '10:30:00', 0, 60),
('21/02/2017', '10:31:00', 0, 60),
('21/02/2017', '10:32:00', 0, 60)
;
中级表
我创建了一个中间表,我将数据转换为CurrentPosture
和Duration
列。我还添加了PreviousPosture
列,以便能够跟踪更改。
CREATE TABLE ActivityPivoted (
[Date] varchar(10),
[Time] varchar(8),
[Duration] Integer,
[CurrentPosture] varchar(20),
[PreviousPosture] varchar(20)
);
INSERT INTO ActivityPivoted
select Date,
Time,
Duration,
CurrentPosture,
lag(CurrentPosture, 1, 'N/A') over(order by Time) as 'PreviousPosture'
from (
select *,
case when Standing>Lying then 'Standing' else 'Lying' end as CurrentPosture,
case when Standing>Lying then Standing else Lying end as Duration
from Activity
) tmp
order by Time
这是它包含的内容:
| Date | Time | Duration | CurrentPosture | PreviousPosture |
|------------|----------|----------|----------------|-----------------|
| 21/02/2017 | 10:15:00 | 60 | Lying | N/A |
| 21/02/2017 | 10:16:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:17:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:18:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:19:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:20:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:21:00 | 43 | Standing | Lying |
| 21/02/2017 | 10:22:00 | 60 | Standing | Standing |
| 21/02/2017 | 10:23:00 | 60 | Standing | Standing |
| 21/02/2017 | 10:24:00 | 46 | Standing | Standing |
| 21/02/2017 | 10:25:00 | 60 | Lying | Standing |
| 21/02/2017 | 10:26:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:27:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:28:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:29:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:30:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:31:00 | 60 | Lying | Lying |
| 21/02/2017 | 10:32:00 | 60 | Lying | Lying |
从那里,它可以非常容易地计算姿势变化的数量
select CurrentPosture,
count(*)
from ActivityPivoted
where CurrentPosture<>PreviousPosture
group by CurrentPosture
结果
| CurrentPosture | |
|----------------|---|
| Lying | 2 |
| Standing | 1 |
不幸的是,由于SQL Server没有重置分区的总和,因此我无法对每个状态分区的持续时间求和。例如:
select *,
sum(Duration) over(partition by CurrentPosture order by Time)
from ActivityPivoted
order by Time
结果:
| Date | Time | Duration | CurrentPosture | PreviousPosture | |
|------------|----------|----------|----------------|-----------------|-----|
| 21/02/2017 | 10:15:00 | 60 | Lying | N/A | 60 |
| 21/02/2017 | 10:16:00 | 60 | Lying | Lying | 120 |
| 21/02/2017 | 10:17:00 | 60 | Lying | Lying | 180 |
| 21/02/2017 | 10:18:00 | 60 | Lying | Lying | 240 |
| 21/02/2017 | 10:19:00 | 60 | Lying | Lying | 300 |
| 21/02/2017 | 10:20:00 | 60 | Lying | Lying | 360 |
| 21/02/2017 | 10:21:00 | 43 | Standing | Lying | 43 |
| 21/02/2017 | 10:22:00 | 60 | Standing | Standing | 103 |
| 21/02/2017 | 10:23:00 | 60 | Standing | Standing | 163 |
| 21/02/2017 | 10:24:00 | 46 | Standing | Standing | 209 |
| 21/02/2017 | 10:25:00 | 60 | Lying | Standing | 420 | < Sum not reset
| 21/02/2017 | 10:26:00 | 60 | Lying | Lying | 480 |
| 21/02/2017 | 10:27:00 | 60 | Lying | Lying | 540 |
| 21/02/2017 | 10:28:00 | 60 | Lying | Lying | 600 |
| 21/02/2017 | 10:29:00 | 60 | Lying | Lying | 660 |
| 21/02/2017 | 10:30:00 | 60 | Lying | Lying | 720 |
| 21/02/2017 | 10:31:00 | 60 | Lying | Lying | 780 |
| 21/02/2017 | 10:32:00 | 60 | Lying | Lying | 840 |
答案 1 :(得分:0)
这是 Gaps and Islands 问题
DECLARE @tab TABLE ([Date] DATE, [Time] TIME, Standing INT, Lying INT )
INSERT INTO @tab
(Date, Time, Standing, Lying)
VALUES
('2017-02-21','10:15:00',0,60),
('2017-02-21','10:16:00',0,60),
('2017-02-21','10:17:00',0,60),
('2017-02-21','10:18:00',0,60),
('2017-02-21','10:19:00',0,60),
('2017-02-21','10:20:00',0,60),
('2017-02-21','10:21:00',43,17),
('2017-02-21','10:22:00',60,0),
('2017-02-21','10:23:00',60,0),
('2017-02-21','10:24:00',46,14),
('2017-02-21','10:25:00',0,60),
('2017-02-21','10:26:00',0,60),
('2017-02-21','10:27:00',0,60),
('2017-02-21','10:28:00',0,60),
('2017-02-21','10:29:00',0,60),
('2017-02-21','10:30:00',0,60),
('2017-02-21','10:31:00',0,60),
('2017-02-21','10:32:00',0,60)
SELECT
Y.[Date]
, Bouts = COUNT(DISTINCT Y.Island) --DISTINCT Islands for number of bouts
, AvBoutTime=CAST((SUM(Y.Lying)/ (COUNT(DISTINCT Y.Island)* 1.0) ) AS DECIMAL(9,1))
FROM
(
SELECT
--Break the dataset down into ISLANDS- using the funky technique
Island = X.RN - ROW_NUMBER()OVER(PARTITION BY X.Date ORDER BY X.RN)
, X.[Date]
, X.[Time]
, X.Standing
, X.Lying
FROM
(
SELECT
--CREATE AN INCREMENTING ID Column like an Identity using ROW_NUmber
--No need for this if there's already is one just missing from the example shown
RN = ROW_NUMBER()OVER(PARTITION BY T.[Date] ORDER BY T.[Time] ASC)
, T.[Date]
, T.[Time]
, T.Standing
, T.Lying
FROM @tab T
) X
WHERE X.Lying > 0
) Y
GROUP BY
Y.[Date]
ORDER BY [Y].[Date]
输出
Date Bouts AvBoutTime
2017-02-21 2 435.5