我正在尝试按照它与两个表的关系数量对表进行排序(让它称之为Parent),让它们称之为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,但如果可能,我想坚持使用标准语法。
答案 0 :(得分:1)
嗯,内存并不差 - 请记住,DBMS(特别是MySQL)有一个规划器,可以动态优化您的查询。您应该在查询中避免使用笛卡尔积,但您的上一次查询与@KaeL提出的确实没有显着差异。中间别名child1_score
和child2_score
在内部只是指针,所以请不要打扰
最后,如果我们不能依赖DBMS的可靠性和性能,我们为什么要使用DBMS?
编辑:要检查查询的准确性,您需要EXPLAIN
http://dev.mysql.com/doc/refman/5.0/en/explain.html
似乎没有办法保留子查询中的中间别名而不在顶级查询中明确选择它们。测试子查询是否按预期工作必须单独完成,然后通过构造嵌套查询进一步优化,并进一步通过EXPLAIN
进行分析。这种方法在我的项目中运行良好。
答案 1 :(得分:1)
你使用MySQL太糟糕了。如果您使用的是任何其他DBMS,则可以使用WITH clause。然后你的查询看起来像这样:
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来完成你想要做的事情。
答案 2 :(得分: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.id
和score
SELECT
。
我猜这个查询应该没问题:
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;