Mysql 如何使用子查询优化此查询?

Mysql 如何使用子查询优化此查询?,mysql,sql,subquery,Mysql,Sql,Subquery,我有以下MySQL查询: SELECT value_1, ( SELECT value_4 FROM table_1 WHERE value_3 < value_1 ORDER BY value_3 DESC LIMIT 1 ) AS result_value FROM table_2 WHERE value_1 BETWEEN 1325372400000 AND 1328050800000 ORDER BY value_1 比如说

我有以下MySQL查询:

SELECT value_1, (
    SELECT value_4 
    FROM table_1
    WHERE value_3 < value_1 
    ORDER BY value_3 DESC  
    LIMIT 1
)
AS result_value 
FROM table_2 
WHERE value_1 BETWEEN 1325372400000 AND 1328050800000  
ORDER BY value_1
比如说

SELECT value_4 
FROM table_1
WHERE value_3 < 1328050800000 
ORDER BY value_3 DESC  
LIMIT 1
表2 MyISAM,4000个条目:

'id', 'int(10) unsigned', 'NO', 'PRI', NULL, 'auto_increment'
'value_3', 'bigint(20) unsigned', 'NO', 'UNI', '0', ''
'value_4', 'bigint(20) unsigned', 'NO', '', '0', ''
'value_1', 'bigint(20) unsigned', 'NO', 'PRI', NULL, ''
解释[查询]:

'1', 'PRIMARY', 'table_2', 'range', 'PRIMARY,value_3_UNIQUE', 'PRIMARY', '8', NULL, '32', 'Using where; Using index'
'2', 'DEPENDENT SUBQUERY', 'table_1', 'index', 'value_3,value_3_value_4', 'value_3', '8', NULL, '1', 'Using where'

使用一点mysql功夫:

SELECT * from
(SELECT value_1, value_4
FROM table_2 
join table_1 on value_3 < value_1
WHERE value_1 BETWEEN 1325372400000 AND 1328050800000  
ORDER BY value_1, value_3 DESC) x
GROUP BY value_1 
ORDER BY value_1
使用mysql的诀窍在于,当您没有分组的列没有聚合时,例如SUM等,您将得到每个组遇到的第一行。如果对有序结果集使用此技术,则可以获得所需的值

这不仅易于编码,而且您会注意到,在表上只进行了一次传递,而不是像您尝试的那样每行进行一次查询。它应该表现良好

编辑: 一些评论者猜测,这种特殊形式的GROUP by是不确定的和/或没有官方支持的,等等。这些评论者指出,在不确定中选择的行,然而,除了第一次遇到的行之外,我从来没有见过也没有听说过mysql选择任何行,并且在无数的生产查询中使用和依赖内部选择上的order by

FWIW,我很高兴推荐这种方法,因为它可靠且值得生产。

如果您在表2中的值_1上有一个索引,在表_1上有一个复合值3,值4索引,那么查询将只使用这些索引

您也可以尝试以下查询:

SELECT value_1
     , value_4 AS result_value 
FROM table_2 
  JOIN table_1
    ON table_1.value_3 =
       ( SELECT value_3
         FROM table_1
         WHERE value_3 < value_1 
         ORDER BY value_3 DESC  
         LIMIT 1
       )
WHERE value_1 BETWEEN 1325372400000 AND 1328050800000  
ORDER BY value_1

在这里,我只是避免使用虚拟桌面。使用虚拟表的主要原因是排序,这是通过在GroupCCont中应用ORDERBY子句实现的

SELECT SUBSTRING_INDEX(group_concat(value_1 
                                    ORDER BY value_1, value_3 DESC),',',1) as value_1, 
       SUBSTRING_INDEX(group_concat(value_4
                                    ORDER BY value_1, value_3 DESC),',',1) as value_4 
FROM table_2 join table_1 on value_3 < value_1 

WHERE value_1 BETWEEN 1325372400000 AND 1328050800000  

GROUP BY value_1  
ORDER BY value_1

表上有什么索引?表1上有值3索引吗?或者一个值3,值4?您可以添加表的定义吗?这些表有多少行?您的泛型值无法提供所需内容的真实上下文。答案可能是以完全不同的方式处理您的查询。如果一些显示上下文的示例数据有限,并且只有那些列有时也会有帮助。我在表2中有索引value_1,value_3,在表中有索引value_3,value_4。这可能会导致对一个非常大的派生表进行排序。这是否保证在所有情况下都返回正确的行,因为您依赖MySQL完全返回每个组中的第一行。据我所知,情况并非如此,基本上是由MySQL为每个属性返回任意值,只要它们属于该组@这可能是真的。操作注意:因为您的范围不匹配,所以行数是无限的。如果这个查询很糟糕,那么它也很糟糕。你得试试别的办法。这完全取决于行数和可用系统resources@stryba:查询将正常工作,并提供正确的结果。至少在您更新MySQL和查询优化器代码之前,必须更改GROUPBY的工作方式。然后这个查询就会中断:因此,即使它现在确实可以工作,我也不会使用它,除非你计划在升级时重新访问它;现在添加后,查询仍以同样的6.6秒计时。@Maximilian:您能在问题中添加表定义和解释输出吗?我已经在问题中添加了表定义。
SELECT SUBSTRING_INDEX(group_concat(value_1 
                                    ORDER BY value_1, value_3 DESC),',',1) as value_1, 
       SUBSTRING_INDEX(group_concat(value_4
                                    ORDER BY value_1, value_3 DESC),',',1) as value_4 
FROM table_2 join table_1 on value_3 < value_1 

WHERE value_1 BETWEEN 1325372400000 AND 1328050800000  

GROUP BY value_1  
ORDER BY value_1