简体   繁体   English

子查询的目的

[英]Purpose of sub-query

I am working on one maintenance project where I need to optimize the query.我正在处理一个需要优化查询的维护项目。 It is very coplex query so I have divided into 5 parts.这是一个非常复杂的查询,所以我分为 5 个部分。

There in one table "document" where fields are在一个表格“文档”中,字段是

document_id(PK)
doc_name
fk_product_id
issue_date
date_expiring
status

Query is查询是

SELECT SQL_CALC_FOUND_ROWS this.* , COUNT(this.document_id) as count_document_id,
FROM ( SELECT * from documents where status != 'D' order by date_expiring desc ) this 

There are millions of records but above query return only record.有数百万条记录,但以上查询仅返回记录。 I don't understand what this query means/ what records will it return.我不明白这个查询是什么意思/它将返回什么记录。

Let's break it down.让我们分解一下。

Starting with the subquery :子查询开始:

SELECT * FROM documents WHERE status != 'D' ORDER BY date_expiring desc

The resultset is a subset of your documents table.结果集是您的documents表的子集。

Next, the main query's FROM :接下来,主查询的FROM

FROM ( /* that subquery up there ^^^ */ ) this

This treats the resultset of the subquery as a virtual table and gives it this for a name.这会将子查询的虚拟表的结果集,并赋予它this一个名字。 MySQL's query optimizer is usually smart enough to avoid extra overhead with this sort of subquery pattern. MySQL 的查询优化器通常足够聪明,可以避免这种子查询模式的额外开销。

Next, we'll look at the SELECT :接下来,我们将看看SELECT

SELECT SQL_CALC_FOUND_ROWS 
       this.* , 
       COUNT(this.document_id) as count_document_id
 FROM ...

SQL_CALC_FOUND_ROWS is deprecated and pointless here, but it does no harm. SQL_CALC_FOUND_ROWS在这里弃用且毫无意义,但它没有坏处。 It's deprecated because there are better ways to count rows.它已被弃用,因为有更好的方法来计算行数。 It's pointless because this query necessarily must return only one row;这是毫无意义的,因为这个查询必须只返回一行; read on.继续阅读。

COUNT(this.document_id) as count_document_id counts all the rows coming from the subquery that contain a non-NULL document_id. COUNT(this.document_id) as count_document_id计算来自包含非 NULL document_id 的子查询的所有行。 But document_id is the primary key of the underlying table so it will never be null.但是document_id是底层表的主键,所以它永远不会为空。 Therefore COUNT(*) would work just as well.因此COUNT(*)也能正常工作。 And, by the way, it makes the subquery's ORDER BY clause entirely pointless.而且,顺便说一下,它使子查询的ORDER BY子句完全没有意义。

Because there's an aggregate function on the SELECT line and no GROUP BY clause, the query aggregates all the rows in the subquery and yields just one row.因为在 SELECT 行上有一个聚合函数并且没有 GROUP BY 子句,所以查询聚合了子查询中的所有行并只产生一行。

this.* is just plain wrong in standard SQL. this.*在标准 SQL 中是完全错误的。 And it's meaningless in MySQL: the single row you get back from this query contains the count: that's fine.它在 MySQL 中毫无意义:您从该查询返回的单行包含计数:很好。 But by specifying this.* you also get back the contents of just one randomly chosen row from the subquery.但是通过指定this.*您还可以从子查询中返回一个随机选择的行的内容。 This will break when you move to MySQL 8.0.当您迁移到 MySQL 8.0 时,这将中断。 MySQL has a notorious nonstandard extension to GROUP BY that enables this sort of random thing. MySQL 对 GROUP BY 有一个臭名昭著的非标准扩展,它支持这种随机的事情。

I hope this helps.我希望这有帮助。 Taking over somebody's code can be loads of fun, eh?接管某人的代码会很有趣,嗯?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM