2016-10-05 9 views
0

私の質問はthis質問に関連していますが、検索フィルターごとに日付の時間が異なるため、個々の検索条件に基づいて特定のカメラを通過した車を取得する

MYSQL/MARIADBスキーマおよびサンプル・データ:

CREATE DATABASE IF NOT EXISTS `puzzle` DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci; 

USE `puzzle`; 

DROP TABLE IF EXISTS `event`; 

CREATE TABLE `event` (
    `eventId` bigint(20) NOT NULL AUTO_INCREMENT, 
    `sourceId` bigint(20) NOT NULL COMMENT 'think of source as camera', 
    `carCode` varchar(40) NOT NULL COMMENT 'ex: A', 
    `carNumber` varchar(40) NOT NULL COMMENT 'ex: 5849', 
    `createdOn` datetime DEFAULT NULL, 
    PRIMARY KEY (`eventId`) 
) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 


INSERT INTO `event` (`eventId`, `sourceId`, `carCode`, `carNumber`, `createdOn`) VALUES 
    (1, 44,'A', '4456', '2016-09-20 20:24:05'), 
    (2, 26,'B', '26484', '2016-09-20 20:24:05'), 
    (3, 5,'A', '4456', '2016-09-20 20:24:06'), 
    (4, 3,'C', '72704', '2016-09-20 20:24:15'), 
    (5, 3,'D' ,'399606', '2016-09-20 20:26:15'), 
    (6, 5, 'A', '4456', '2016-09-20 20:27:25'), 
    (7, 44,'C', '72704', '2016-09-20 20:29:25'), 
    (8, 3,'A' ,'4456', '2016-09-20 20:30:55'), 
    (9, 44,'B' ,'26484', '2016-09-20 20:34:55'), 
    (10, 26,'B' ,'4456', '2016-09-20 20:35:15'), 
    (11, 3, 'C','72704', '2016-09-20 20:35:15'), 
    (12, 3,'D', '399606', '2016-09-20 20:44:35'), 
    (13, 26,'A' ,'4456', '2016-09-20 20:49:45'); 

要件:

ユーザーが2つの検索フィルタを持っています。

彼は最初の検索フィルターで、特定の日付と時刻にsourceId(44,3)を持つすべての車を取得します。 (e.createdOn> '2016-09-20 20:24:00'とe.createdOn < '2016-09-20 20:35:00 ')

2番目の検索フィルタでは、別の日時のためにsourceIdが(26,3,5)にある車。今、私はすべて(carNumbersを取得したい(e.createdOn> '2016年9月20日20時36分○○秒' とe.createdOn < '2016年9月20日午後08時49分○○秒')

を仮定carCode)を使用します。

実際のテーブルには3億以上のレコードが含まれているため、クエリが高速になる必要があります。これまでに以下の

は、SQLは、この問題を解決することはできませんか私はバックエンドのコーディングを使用する必要がある場合、私は疑問に思う私は、クエリで行くことができる最大値(そのも有効な結果を生成していない)

select distinct e1.carNumber, e1.carCode from event e1 

    inner join (select e2.carNumber, e2.carCode from event e2 where e2.sourceId in (44,3)) e3 on e1.carNumber= e3.carNumber 
    inner join (select e2.carNumber, e2.carCode from event e2 where e2.sourceId in (44,3) ) e4 on e1.carCode= e4.carCode 

    inner join (select e2.carNumber, e2.carCode from event e2 where e2.sourceId in (26,3,5)) e5 on e1.carNumber= e5.carNumber 
    inner join (select e2.carNumber, e2.carCode from event e2 where e2.sourceId in (26,3,5)) e6 on e1.carCode= e6.carCode 

のですか?

使用中のMySQL/MariaDBのバージョン:

mariadb-5.5.50

のmysql-5.5.51

+0

なぜ4つの結合を行うのですか?あなたの拘束でwhere節を実行します。各サブクエリは300Mを読み込みます。あなたは5 * 300M行を読むことを意味します。 – AxelH

+0

Bascially私は両方の検索フィルターの結果を交差させたい。 –

答えて

0

これはあなたの状態の読み取り

select distinct e1.carNumber, e1.carCode from event e1 
    where e.sourceId in (44,3) 
    and e.createdOn = "certain date" 
    and exists (
     select 'x' from event e2 
      where e2.sourceId in (26,3,5) 
      and e2.createdOn = "another date" 
      and e1.carCode = e2.carCode 
      and e1.carNumber = e2.carNumber 
    ) 
から私の推測になります

第2のフィルタの選択から存在する第1のフィルタからすべてのかごを返す

一度に1部ずつ読む:

select distinct e1.carNumber, e1.carCode from event e1 
    where e.sourceId in (44,3) 
    and e.createdOn = "certain date" 

最初のフィルタからすべての車が返されます。それで、2番目のフィルタで再度フィルタリングする必要があります。

select 'x' from event e2 
     where e2.sourceId in (26,3,5) 
     and e2.createdOn = "another date" 
     and e1.carCode = e2.carCode 
     and e1.carNumber = e2.carNumber 

私はすでに存在している最初の結果では車で結果があるかどうかを確認するためにexists句を使用します。

EDIT 2:最後の編集あなたが要求を追加し続けるので...例えば

select distinct e1.carNumber, e1.carCode from event e1 
     inner join event e2 on e1.carCode = e2.carCode and e1.carNumber = e2.carNumber and e2.sourceId in (26,3,5) and e2.createdOn = "another date" --the second filter 
     -- inner join event e3 on e1.carCode = e3.carCode and e1.carNumber = e3.carNumber and e3.sourceId in (x,y,z) and e3.createdOn = "some crazy date" --the third filter ... 
    where e.sourceId in (44,3) and e.createdOn = "certain date" --the first filter 
+0

有効な共通の結果を得るには、車の番号と車のコードを一致させる必要があります。 –

+0

サブクエリで「x」を選択する理由を説明してください。 –

+0

2つの結果の交差をどのように実行していますか? –

0

(正確にはあなたの後ろのものではないかもしれません)

SELECT carnumber 
    FROM event 
WHERE (sourceid IN (44,3) AND createdon BETWEEN '2016-09-20 20:24:00' and '2016-09-20 20:35:00') 
    OR (sourceid IN (26,3,5) AND createdon BETWEEN '2016-09-20 20:36:00' and '2016-09-20 20:49:00') 
GROUP 
    BY carnumber HAVING COUNT(*) > 1; 
+0

1つのcarnumber、carcode occurencesがsourceId = 44で2回の場合、その結果が表示されますが、そのカーナンバーがソース(26,3,5)で利用できないために持ち込むべきではないため、2つの結果の交差が正しく行われません。 –

+1

この場合、参加は – Strawberry

+0

@Strawberryで十分です。私はその方法で作業しましたが、彼にとっては大丈夫とは思われません。 – AxelH

0

私の問題を解決するために、以下のクエリを使用しました。それが他人を助けることを願って

SELECT e1.carCode, e1.carNumber from event e1 

WHERE (sourceid IN (44,3) AND createdon BETWEEN '2016-09-20 20:24:00' and '2016-09-20 20:35:00') 
    OR (sourceid IN (26,3,5) AND createdon BETWEEN '2016-09-20 20:36:00' and '2016-09-20 20:49:00') 

group by e1.carCode, e1.carNumber 
having sum(e1.sourceId IN (44,3)) > 0 and 
     sum(e1.sourceId IN (26,3,5)) > 0; 
関連する問題