2

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

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 に答える
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 に答える
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ます。scoreSELECT

このクエリは問題ないと思います:

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 に答える