0

我尝试从特定类型中获取最多类型的条目。为了清楚起见,我将从示例开始。我的列类型实际上是一个外键。

例子:

我的计数器表(~ 1.500.000 行),它计算了所有在不同红绿灯处看到的汽车:

id, datetime, type, traffic_light_id
0, '09:59', 'red ford', 2
1, '10:00', 'black bmw', 1
2, '10:11', 'red ford', 1
3, '10:30', 'yellow ford', 1
4, '11:01', 'black bmw', 1
5, '11:09', 'red ford', 1
6, '11:18', 'green mercedes', 1
7, '11:20', 'black bmw', 2
8, '11:44', 'white renault', 2
9, '11:44', 'red renault', 1

我在每一列都有一个索引。id 是主键。

需要:

所以我想得到的是“black bmw”的结果,traffic_light_id = 1。结果应该总结所有之前和之后看到的“黑色宝马”类型的汽车。

结果应该是:

count, type, traffic_light_id
2, 'red ford', 1
1, 'yellow ford', 1

我的坏解决方案:

因此,到目前为止,我的解决方案是遍历计数器中 type = 'black bmw' 和 traffic_light_id = 1 的所有计数。

对于每个计数,我都会在我的 php 脚本中获得带有 traffic_light_id 的 bevore 和 after seen 元素(对每个计数另外进行两个查询)。

之后,我按数组中给定的汽车类型对结果进行分组并计算它们的频率。

对于这样的事情有更好的解决方案吗?最好的事情是只有一个 sql 查询!

4

2 回答 2

2

我首先了解到您想要一个简单的组:

select type, count(*) as totalseen,
       sum(case when traffic_light_id = 1 then 1 else 0 end) as SeenTrafficLight1
from t
group by type

如果你真的只想要红绿灯 = 1,那么使用一个where子句:

select type, traffic_light_id, count(*)
from t
where traffic_light_id  = 1
group by type

博特,谢谢你的澄清。这使问题变得更加有趣。

以下是我们如何使用相关子查询来做到这一点。这是之前类型的示例:

select typeBefore, count(*)
from (select t.*,
             (select type from t t2 where t2.datetime < t.datetime order by t2.datetime desc limit 1
            ) as typeBefore,
             (select type from t t2 where t2.datetime > t.datetime order by t2.datetime limit 1
            ) as typeAfter
      from t
     ) t
where type = 'black,bmw' and traffic_light_id = 1
group by typeBefore

子查询使用日期时间来确定之前的版本。如果id是主键并以相同的方式排序,则可以使用它。

然后过程稍微复杂一些。这是通过交叉连接到具有两行的表的一种方法。这使得可以同时进行typeBefore分组typeAfter

select (case when which = 'Before' then typeBefore else typeAfter end), count(*)
from (select t.*,
             (select type from t t2 where t2.datetime < t.datetime order by t2.datetime desc limit 1
            ) as typeBefore,
             (select type from t t2 where t2.datetime > t.datetime order by t2.datetime limit 1
            ) as typeAfter
      from t
     ) t cross join
     (select 'before' as which union all select 'after') const
where type = 'black,bmw' and traffic_light_id = 1
group by (case when which = 'Before' then typeBefore else typeAfter end)
于 2013-01-23T15:21:17.087 回答
0

它是紧随其后和之前的计数,对吗?

这是一个很好的问题...

(我确实使用这个表变量来构建我的查询,将它替换为查询中的表或用我的变量进行测试)

    declare @T table(id int,[datetime] time,[type] varchar(max) ,traffic_light_id int)
    insert into @T (id,datetime,type,traffic_light_id)
    values
    (0, '09:59', 'red ford', 2)
    ,(1, '10:00', 'black bmw', 1)
    ,(2, '10:11', 'red ford', 1)
    ,(3, '10:30', 'yellow ford', 1)
    ,(4, '11:01', 'black bmw', 1)
    ,(5, '11:09', 'red ford', 1)
    ,(6, '11:18', 'green mercedes', 1)
    ,(7, '11:20', 'black bmw', 2)
    ,(8, '11:44', 'white renault', 2)
    ,(9, '11:44', 'red renault', 1)

也许这样的事情可以解决问题?

select COUNT(*) as [count],OA.type,OA.traffic_light_id
        from @t T
        outer apply(select type,traffic_light_id 
                    from (select top 1 type,traffic_light_id 
                            from @T T_after
                            where T_after.datetime > T.datetime
                            order by T_after.datetime
                    )V_after
                    union all 
                    select type,traffic_light_id 
                    from (select top 1 type,traffic_light_id from @T T_before
                            where T_before.datetime < T.datetime
                            order by T_before.datetime desc
                    )V_before
        )OA
        where T.traffic_light_id = 1
        and T.type = 'black bmw'
        group by OA.type,OA.traffic_light_id
于 2013-01-23T16:30:02.260 回答