寻找最有效的选择查询

时间:2019-06-30 19:12:23

标签: mysql sql query-optimization

我有一张表,需要在不同的行上显示结果,在一列中必须存在不同的键值。

我每天通过REST API从另一个系统获取此表一次,并在我的MySQL DB中进行如下查找(简化):

+----+------+------------+-------+
| ID | type | date       | value |
+----+------+------------+-------+
|  1 | A    | 2019-06-01 |     1 |
|  2 | B    | 2019-06-01 |     2 |
|  3 | A    | 2019-06-02 |     4 |
|  4 | B    | 2019-06-03 |     5 |
|  9 | A    | 2019-06-09 |    11 |
| 10 | B    | 2019-06-09 |    14 |
| 11 | A    | 2019-06-24 |    99 |
+----+------+------------+-------+

现在,我需要一个选择,该选择仅在同时存在类型A和类型B的值的情况下全部生成。结果应如下所示:

+------------+-------+--------+----+------+------------+-------+
| date       | typeA | valueA | ID | type | date       | value |
+------------+-------+--------+----+------+------------+-------+
| 2019-06-01 | A     |      1 |  2 | B    | 2019-06-01 |     2 |
| 2019-06-09 | A     |     11 | 10 | B    | 2019-06-09 |    14 |
+------------+-------+--------+----+------+------------+-------+
  • 第一个想法:

使用子选择...对于大表来说可能不是个好主意...但我不确定。

SELECT * from 
(SELECT date as dateA, value as valueA from V1 where type = 'A') AS subA,
(SELECT date as dateB, value as valueB from V1 where type = 'B') AS subB
WHERE dateA = dateB
  • 第二个想法:

创建两个临时表,然后加入一个联接。但是需要时间来创建两个表以及两个新临时表之间的联接。

CREATE TEMPORARY table tA SELECT date, type as typeA, value as valueA from V1 WHERE type = 'A';
CREATE TEMPORARY table tB SELECT date, type as typeB, value as valueB from V1 WHERE type = 'B';

SELECT * from tA 
INNER JOIN tB on tA.date = tB.date;
  • 第三个想法:

仅在临时表上创建并将其用于使用主表的联接:

CREATE TEMPORARY table tB SELECT * from V1 WHERE type = 'B';

SELECT * from V1 
INNER JOIN tB on V1.date = tB.date
where V1.type = 'A'

我的哪个想法最适合大型桌子,还是有更好的解决方案?

谢谢。

4 个答案:

答案 0 :(得分:2)

您需要一个自我内部联接

select select v1.date,v1.type as typeA, v1.value as valueA, 
       v2.id, v2.type as typeB, v2.date, v2.value
  from v v1 join v v2    -- v is table name
    on v1.date = v2.date
    and v1.type = 'A' and v2.type = 'B';

+------------+-------+--------+----+------+------------+-------+
| date       | typeA | valueA | ID | type | date       | value |
+------------+-------+--------+----+------+------------+-------+
| 2019-06-01 | A     |      1 |  2 | B    | 2019-06-01 |     2 |
| 2019-06-09 | A     |     11 | 10 | B    | 2019-06-09 |    14 |
+------------+-------+--------+----+------+------------+-------+

Demo

答案 1 :(得分:1)

一种有效的方法可能是基于不同计数= 2的日期与ype A的表itesel以及b类型的一个tyme之间的内部联接

    select t.date, t1.type typeA, t1.value valueA, t2.type typeB, t2.value valueB, 
    from (
        select  date
        from  my_table  
        group by  date  
        having count(distinct type) = 2
    ) t 
    inner join  my_table t1 on t1.date = t.date and type='A'
    inner join  my_table t2 on t2.date = t.date and type='B'        

答案 2 :(得分:1)

这可能不是最显而易见的查询。
但这很有意义,因为您将重点放在日期上并将类型与日期合并。
性能将非常取决于所使用的未知索引。

SELECT 
 *
FROM (

  SELECT 
     date
   , MAX(CASE WHEN type = 'A' THEN type END) AS  typeA
   , MAX(CASE WHEN type = 'A' THEN value END) AS  valueA
  FROM 
   your_table
  WHERE
   type = 'A' 
  GROUP BY 
   date  
) AS a_type 
INNER JOIN (

  SELECT 
     date
   , MAX(CASE WHEN type = 'B' THEN type END) AS  typeB
   , MAX(CASE WHEN type = 'B' THEN value END) AS  valueB  
  FROM 
   your_table
  WHERE
   type = 'B' 
  GROUP BY 
   date   
) AS b_type
ON
 a_type.date = b_type.date

结果

| date       | typeA | valueA | date       | typeB | valueB |
| ---------- | ----- | ------ | ---------- | ----- | ------ |
| 2019-06-01 | A     | 1      | 2019-06-01 | B     | 2      |
| 2019-06-09 | A     | 11     | 2019-06-09 | B     | 14     |

请参阅demo

答案 3 :(得分:1)

如果每个日期只能有每种类型的一种(即同一日期不能有2个“ A”或2个“ B”),则可以按日期分组并使用条件汇总来获取值用于不同的类型。

select
    date,
    max(case when type = 'A' then id end) idA,
    max(case when type = 'A' then value end) valueA,
    max(case when type = 'B' then id end) idB,
    max(case when type = 'B' then value end) valueB
from V1
where type in ('A', 'B') -- only necessary if other types exist
group by date
having count(distinct type) = 2

http://sqlfiddle.com/#!9/69b9f/1