【问题标题】:Get the cars that passed specific cameras based on individual search criteria根据个人搜索条件获取通过特定摄像头的汽车
【发布时间】:2016-10-05 11:22:58
【问题描述】:

我的问题与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');

要求:

用户有两个搜索过滤器。

在他说的第一个搜索过滤器中,让我在特定日期和时间获取所有在 (44,3) 中具有 sourceId 的汽车。假设(e.createdOn > '2016-09-20 20:24:00' 和 e.createdOn

在第二个搜索过滤器中,他说,将 sourceId 在 (26,3,5) 中的所有汽车获取另一个日期和时间。假设(e.createdOn > '2016-09-20 20:36:00' 和 e.createdOn

现在我想获取两个搜索结果中可用的所有(carNumbers、carCode)。

查询需要快速,因为真实表包含超过 3 亿条记录。

到目前为止,以下是我可以查询的最大值(它甚至没有产生有效的结果)

    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 

我想知道 SQL 是否能够解决这个问题,还是我应该使用后端编码?

正在使用的 MySQL / MariaDB 版本:

mariadb-5.5.50

mysql-5.5.51

【问题讨论】:

  • 你为什么要做4个join?用你的约束做一个 where 子句。每个子查询将读取 300M。意思是你读了 5*300M 行。
  • 基本上我想获得两个搜索过滤器的相交结果。

标签: mysql sql mariadb


【解决方案1】:

这将是我从阅读您的情况中得出的猜测

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
    )

从第二个过滤器的选择中返回来自第一个过滤器的所有汽车

一次读一部分:

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

将从第一个过滤器返回所有汽车。从此,我们需要用第二个过滤器再次过滤。

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 子句检查第一个结果中是否有汽车已经存在的结果。

编辑 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

【讨论】:

  • 车牌号和车号要匹配才有效。
  • 你能解释一下,为什么在子查询中选择'x'。
  • 两个结果的交集效果如何?
  • 我明白你的意思。您能否告诉我,如果不是两个,而是三个搜索过滤器,我将如何使这个查询动态化?
  • 你能编辑并提供加入解决方案吗?因为稍后我们计划增加搜索过滤器。谢谢
【解决方案2】:

例如(可能并不完全是你所追求的)

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;

【讨论】:

  • 如果一个车号,carcode 在 sourceId = 44 中出现两次,它会带来它的结果,但它不应该带来,因为该车号在源 (26,3,5) 中不可用,所以相交两个结果中的一个未正确完成。
  • 在这种情况下,加入就足够了
  • @Strawberry 我确实是这样做的,但对他来说似乎不太合适。
【解决方案3】:

我使用以下查询来解决我的问题。希望对其他人有所帮助。

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;

【讨论】:

    猜你喜欢
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 2018-09-14
    • 1970-01-01
    • 2020-09-05
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多