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 は主キーです。

必要:

したがって、私が取得したいのは、traffic_light_id = 1 の 'black bmw' の結果です。結果は、'black bmw' で見られたタイプの車の前と後のすべてを合計する必要があります。

結果は次のようになります。

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 要素も取得します (カウントごとにさらに 2 つのクエリが作成されます)。

その後、配列内の指定された車のタイプで結果をグループ化し、その頻度を数えます。

そのようなものに対するより良い解決策はありますか?最善の方法は、SQL クエリを 1 つだけにすることです。

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が主キーで、順序が同じであれば、それを使用できます。

次に、プロセスはもう少し複雑です。2 つの行を持つテーブルにクロス ジョインすることで、これを行う 1 つの方法を次に示します。これにより、グループ化と同時に次のことが可能になり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 に答える