2

我正在尝试根据它与两个表的关系数对表(我们称之为父)进行排序,我们称它们为 Child1 和 Child2)。现在我正在这样做:

SELECT Master.id
 (SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) 
 + (SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS  score
 ORDER BY score DESC;

它按预期工作,但难以维护,因为我无法知道子查询的中间值是什么。我想要的是以下内容:

 SELECT Master.id
 (SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) AS child1_score,
 (SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS  child2_score,
 child1_score + child2_score AS score
 ORDER BY score DESC;

但这给了我一个错误,说 child1_score 和 child2_score 没有定义。我能想到的唯一干净的方法是使用额外级别的嵌套子查询:

SELECT child1_score + child2_score AS score, id FROM
    (SELECT Master.id
     (SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) AS child1_score,
     (SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS  child2_score)
    ORDER BY score DESC;

但这似乎对记忆来说会更糟。

有没有更好的方法来处理这个我没有看到的?我正在使用 MySQL,但如果可能的话,我想坚持使用标准语法。

4

3 回答 3

1

好吧,这对内存来说并没有更糟 - 请记住 DBMS(尤其是 MySQL)有一个规划器并动态优化您的查询。您应该在查询中避免笛卡尔积,但您的最后一个查询和@KaeL 提出的查询之间确实没有显着差异。中间别名child1_scorechild2_score内部只是指针,所以请不要打扰。
最后,如果我们不能依赖 DBMS 的可靠性和性能,我们为什么要使用 DBMS?

编辑:为了检查您的查询将如何执行,您需要EXPLAIN http://dev.mysql.com/doc/refman/5.0/en/explain.html
似乎没有办法从子查询中保留中间别名无需在顶级查询中明确选择它们。测试子查询是否按预期工作必须单独完成,然后通过构建嵌套查询并进一步通过分析进行优化EXPLAIN。这种方法在我的项目中效果很好。

于 2013-07-09T07:31:48.737 回答
1

你使用 MySQL 太糟糕了。如果您正在使用任何其他 DBMS,则可以使用WITH 子句。然后您的查询将如下所示:

WITH First AS (
    SELECT id, COUNT(*) AS Cnt FROM Child1 GROUP BY id
),
Second AS (
    SELECT id, COUNT(*) AS Cnt FROM Child2 GROUP BY id
)
SELECT Master.id, First.Cnt, Second.Cnt, First.Cnt+Second.Cnt as score
    FROM Master
    INNER JOIN First ON Master.id=First.id
    INNER JOIN Second ON Master.id=Second.id
    ORDER BY score DESC;

使用此方法,您可以添加任意数量的中间子查询,并且您也可以引用来自早期子查询的列(不仅仅是在最后一个子查询中)。不幸的是,我不确定是否有办法单独使用 MySQL 来完成您尝试做的事情。

于 2014-09-28T06:32:44.197 回答
0

根据您的最后一个查询:

SELECT child1_score + child2_score AS score, id FROM
    (SELECT Master.id
     (SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) AS child1_score,
     (SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS  child2_score)
    ORDER BY score DESC;

让我觉得你只需要Master.idscoreSELECT教育。

我想这个查询应该没问题:

SELECT Master.id
(SELECT COUNT(*) FROM Child1 WHERE Child1.id=Master.id) + (SELECT COUNT(*) FROM Child2 WHERE Child2.id=Master.id) AS score
FROM Master
ORDER BY score DESC;
于 2013-07-09T07:24:37.380 回答