在这种情况下,我通过子查询加入并希望将deptid传递给已连接的子查询,但我得到'D is not defined'错误消息。
SELECT *
FROM(
SELECT D.name AS deptname,D.id AS deptid,WT.sortposition AS deptsortposition
FROM departments D JOIN web_taxonomy WT ON (WT.deptid=D.id AND WT.classid=0)
WHERE D.web=1
ORDER BY sortposition
) AS D
LEFT JOIN (
SELECT C.name AS classname,C. id AS classid,C.department,WT.sortposition AS classsortposition,WT.deptid
FROM classes C
JOIN web_taxonomy WT ON (WT.classid=C.id AND WT.subclassid=0 AND WT.deptid=D.deptid)
WHERE web=1 ORDER BY classsortposition
) AS C ON (C.department=D.deptid)
任何方式传递引用类似于我在上面的强标签中包含的内容?
编辑:我犯了一个错误,最初离开了工作查询,只是添加了我想要运行的部分。基本上我想通过仅获取与D子查询表中找到的共享相同deptid的行来最小化连接子查询的大小。
答案 0 :(得分:10)
您在别名的子查询中不能使用别名“D”。
这应该可行(在第一个子查询中只使用X而不是D - 不是严格必要但有助于提高可读性 - 并将对D的引用移到第二个子查询之外):
SELECT *
FROM(
SELECT
X.name AS deptname
, X.id AS deptid
, WT.sortposition AS deptsortposition
FROM departments X
JOIN web_taxonomy WT ON (WT.deptid=X.id AND WT.classid=0)
WHERE X.web=1
ORDER BY sortposition
) AS D -- this is available to objects referencing this alias
LEFT JOIN (
SELECT
C.name AS classname
, C. id AS classid
, C.department
, WT.sortposition AS classsortposition
, WT.deptid
FROM classes C JOIN web_taxonomy WT
ON WT.classid=C.id AND WT.subclassid=0
WHERE web=1 ORDER BY classsortposition
) AS C ON C.department=D.deptid AND C.deptid = D.deptid -- i.e. here
答案 1 :(得分:6)
我认为你根本不需要做子查询:
SELECT D.name AS deptname, D.id AS deptid, WT1.sortposition AS deptsortposition,
C.name AS classname, C.id AS classid, C.department,
WT2.sortposition AS classsortposition, WT2.deptid
FROM departments AS D
JOIN web_taxonomy AS WT1 ON (WT1.deptid=D.id AND WT1.classid=0)
LEFT OUTER JOIN web_taxonomy AS WT2 ON (WT2.deptid=D.id AND WT2.subclassid=0)
LEFT OUTER JOIN classes AS C ON (C.id=WT2.classid AND C.department=WT2.deptid);
WT1的加入应该受益于索引:
ALTER TABLE web_taxonomy
ADD KEY wt_dept_class (deptid, classid),
ADD KEY wt_dept_subclass (deptid, subclassid);
类的连接使用该表的PRIMARY键索引。
以下是此查询的EXPLAIN输出:
+----+-------------+-------+--------+--------------------------+---------------+---------+------------------+------+-----------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+--------------------------+---------------+---------+------------------+------+-----------------------+
| 1 | SIMPLE | D | ALL | PRIMARY,id | NULL | NULL | NULL | 1 | NULL |
| 1 | SIMPLE | WT1 | ref | dept_class,dept_subclass | dept_class | 10 | test.D.id,const | 1 | Using index condition |
| 1 | SIMPLE | WT2 | ref | dept_class,dept_subclass | dept_subclass | 10 | test.D.id,const | 1 | Using where |
| 1 | SIMPLE | C | eq_ref | PRIMARY,id | PRIMARY | 8 | test.WT2.classid | 1 | Using where |
+----+-------------+-------+--------+--------------------------+---------------+---------+------------------+------+-----------------------+
说实话,我必须稍微编辑一下EXPLAIN报告来显示结果。我测试了零行的表,因此优化器错误地选择了WT2的dept_class索引。如果您使用真实数据进行测试,我认为它会正确选择dept_subclass索引。
我尝试了你的查询,通过一个小修改来解决D.deptid上的错误:
SELECT *
FROM(
SELECT D.name AS deptname,D.id AS deptid,WT.sortposition AS deptsortposition
FROM departments D JOIN web_taxonomy WT ON (WT.deptid=D.id AND WT.classid=0)
WHERE D.web=1
ORDER BY sortposition
) AS D
LEFT JOIN (
SELECT C.name AS classname,C. id AS classid,C.department,WT.sortposition AS classsortposition,WT.deptid
FROM classes C
JOIN web_taxonomy WT ON (WT.classid=C.id AND WT.subclassid=0 AND WT.deptid=C.department)
WHERE web=1 ORDER BY classsortposition
) AS C ON (C.department=D.deptid);
EXPLAIN报告:
+----+-------------+------------+------+--------------------------+------------+---------+-----------------------------+------+----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+------+--------------------------+------------+---------+-----------------------------+------+----------------------------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 2 | NULL |
| 1 | PRIMARY | <derived3> | ALL | NULL | NULL | NULL | NULL | 2 | Using where; Using join buffer (Block Nested Loop) |
| 3 | DERIVED | C | ALL | PRIMARY,id | NULL | NULL | NULL | 1 | Using where; Using temporary; Using filesort |
| 3 | DERIVED | WT | ref | dept_class,dept_subclass | dept_class | 10 | test.C.department,test.C.id | 1 | Using index condition; Using where |
| 2 | DERIVED | D | ALL | PRIMARY,id | NULL | NULL | NULL | 1 | Using where; Using temporary; Using filesort |
| 2 | DERIVED | WT | ref | dept_class,dept_subclass | dept_class | 10 | test.D.id,const | 1 | Using index condition |
+----+-------------+------------+------+--------------------------+------------+---------+-----------------------------+------+----------------------------------------------------+
呸!它为部门和类运行一个表扫描(这是类型列中的ALL
),它为每个子查询创建一个临时表,然后将它们连接到而不用任何好处索引(这是Using join buffer
的含义)。这不是一个有趣的优化计划。
通常,排序应该是SQL查询的最后一部分。不要尝试对子查询结果进行排序以解决优化器问题。如果可能,您希望索引可以辅助连接,但是连接的最佳索引的顺序不一定是您希望返回最终结果的顺序。所以让优化器完成其工作以进行连接,然后对最终结果进行排序。
SELECT D.name AS deptname, D.id AS deptid, WT1.sortposition AS deptsortposition,
C.name AS classname, C.id AS classid, C.department,
WT2.sortposition AS classsortposition, WT2.deptid
FROM departments AS D
JOIN web_taxonomy AS WT1 ON (WT1.deptid=D.id AND WT1.classid=0)
LEFT OUTER JOIN web_taxonomy AS WT2 ON (WT2.deptid=D.id AND WT2.subclassid=0)
LEFT OUTER JOIN classes AS C ON (C.id=WT2.classid AND C.department=WT2.deptid)
ORDER BY deptsortposition, classsortposition;
这仍然使用一个临时表&amp; filesort,但不是两个。它避免了连接缓冲区;每个联接都是索引辅助的。
+----+-------------+-------+--------+--------------------------+---------------+---------+------------------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+--------------------------+---------------+---------+------------------+------+---------------------------------+
| 1 | SIMPLE | D | ALL | PRIMARY,id | NULL | NULL | NULL | 1 | Using temporary; Using filesort |
| 1 | SIMPLE | WT1 | ref | dept_class,dept_subclass | dept_class | 10 | test.D.id,const | 1 | Using where; Using index |
| 1 | SIMPLE | WT2 | ref | dept_subclass | dept_subclass | 10 | test.D.id,const | 1 | Using where |
| 1 | SIMPLE | C | eq_ref | PRIMARY,id | PRIMARY | 8 | test.WT2.classid | 1 | Using where |
+----+-------------+-------+--------+--------------------------+---------------+---------+------------------+------+---------------------------------+