id zoneid status 1 35 IN starting zone 2 35 OUT 1st trip has been started 3 36 IN 4 36 IN 5 36 OUT 6 38 IN last station zone 1 trip completed 7 38 OUT returning back 2nd trip has start 8 38 OUT 9 36 IN 10 36 OUT 11 35 IN when return back in start zone means 2nd trip complete 12 35 IN 13 35 IN 14 35 OUT 3rd trip has been started 15 36 IN 16 36 IN 17 36 OUT 18 38 IN 3rd trip has been completed 19 38 OUT 4th trip has been started 20 38 OUT 21 36 IN 22 36 OUT 23 35 IN 4th trip completed 24 35 IN
现在我想要一个SQL查询,所以我可以算不上旅行。我不想使用状态字段进行计数 修改
我想要结果总旅行 其中35是起点,38是结束点(这是1次旅行),38次后发生35次意味着2次旅行,依此类推。
答案 0 :(得分:2)
因此,您不希望查看状态,但只查看按ID排序的zoneid
更改。 zoneid
36无关紧要,因此我们只选择35和38,按ID和计数更改排序。我们通过将记录与前一个记录进行比较来检测更改。我们可以用LAG查看以前的记录。
select sum(ischange) as trips_completed
from
(
select
case when zoneid <> lag(zoneid) over (order by id) then 1 else 0 end as ischange
from trips
where zoneid in (35,38)
) changes_detected;
答案 1 :(得分:1)
我建议不做任何测试。以下查询是否生成正确的行数?请注意,如果有一个date_created(datetime)列,那么我建议使用该列来排序而不是id。
select
ca.in_id, t.id as out_id, ca.in_status, t.status as out_status
from table1 t
cross apply (
select top (1) id as in_id, status as in_status
from table1
where table1.id < t.id
and zoneid = 35
order by id DESC
) ca
where t.zoneid = 38
/* and conditions for selecting one day only */
如果该逻辑正确,那么只需使用COUNT(*)而不是列列表。
CREATE TABLE Table1
("id" int, "zoneid" int, "status" varchar(3), "other" varchar(54))
;
INSERT INTO Table1
("id", "zoneid", "status", "other")
VALUES
(1, 35, 'IN', 'starting zone'),
(2, 35, 'OUT', '1st trip has been started'),
(3, 36, 'IN', NULL),
(4, 36, 'IN', NULL),
(5, 36, 'OUT', NULL),
(6, 38, 'IN', 'last station zone 1 trip completed'),
(7, 38, 'OUT', 'returning back 2nd trip has start'),
(8, 38, 'OUT', NULL),
(9, 36, 'IN', NULL),
(10, 36, 'OUT', NULL),
(11, 35, 'IN', 'when return back in start zone means 2nd trip complete'),
(12, 35, 'IN', NULL),
(13, 35, 'IN', NULL),
(14, 35, 'OUT', '3rd trip has been started'),
(15, 36, 'IN', NULL),
(16, 36, 'IN', NULL),
(17, 36, 'OUT', 'other'),
(18, 38, 'IN', '3rd trip has been completed'),
(19, 38, 'OUT', '4th trip has been started'),
(20, 38, 'OUT', NULL),
(21, 36, 'IN', NULL),
(22, 36, 'OUT', NULL),
(23, 35, 'IN', '4th trip completed'),
(24, 35, 'IN', NULL)
;
答案 2 :(得分:1)
出于学习目的,这里有一个自我解释的&amp;详细版本http://sqlfiddle.com/#!15/d8bf4/1/0
该解决方案基于计算“跑步”&#39;从&#35; 35到38&#39;和&#39; 38到35&#39;。解决方案非常特定于OP查询,但可以使用更短的版本进行优化...
with trip_38_to_35 as (
select * from zonecount
where (zoneid=38 and status='OUT') OR (zoneid=35 and status='IN')
order by id asc
)
, count_start_on_38 as (
select count(*) as start_on_38
from trip_38_to_35
where (zoneid=38 and status='OUT') AND
id <
( select max(id)
from trip_38_to_35
where (zoneid=35 and status='IN')
) /*do not count unfinished trips*/
)
, count_end_on_35 as (
select count(*) as end_on_35
from trip_38_to_35
where (zoneid=35 and status='IN')
) /*the other way of trip*/
, trip_35_to_38 as (
select * from zonecount
where (zoneid=35 and status='OUT') OR (zoneid=38 and status='IN')
order by id asc
)
,count_start_on_35 as (
select count(*) as start_on_35
from trip_35_to_38
where (zoneid=35 and status='OUT') AND
id <
( select max(id)
from trip_35_to_38
where (zoneid=38 and status='IN')
) /*do not count unfinished trips*/
)
,count_end_on_38 as (
select count(*) as end_on_38
from trip_35_to_38
where (zoneid=38 and status='IN')
)
/*sum the MIN of the two trips count*/
select
(case when end_on_35 > start_on_38 then start_on_38 else end_on_35 end) +
(case when end_on_38 > start_on_35 then start_on_35 else end_on_38 end)
from
count_start_on_38,
count_end_on_35,
count_start_on_35,
count_end_on_38
顺便说一下,按照定义计算了6次旅行