2016-11-07 7 views
1

私はフレームワーク(Magento)を使っているので、実際に実行されるSQLを直接制御することはできません。クエリのさまざまな部分を構築することができますが、異なるコンテキストでは、データベースに行く前にさまざまな方法で変更します。カウントと行の両方に対してmysqlクエリの本体を再利用

ここに私が取り組んでいるものの単純化された例があります。

students  enrolments 
--------  ------------------ 
id| name  student_id| class 
--+-----  ----------+------- 
1| paul     1|biology 
2|james     1|english 
3| jo     2| maths 
         2|english 
         2| french 
         3|physics 
         3| maths 

と一緒に、これらの学生は上の登録されているすべてのコースを英語を勉強している学生全員を表示するクエリは、次のようになります。

SELECT name, GROUP_CONCAT(enrolments.class) AS classes 
FROM students LEFT JOIN enrolments ON students.id=enrolments.student_id 
WHERE students.id IN (SELECT e.student_id 
         FROM enrolments AS e 
         WHERE e.class LIKE "english") 
GROUP BY students.id 

これは期待通りの結果

name|    classes 
----+---------------------- 
paul|biology, english 
james|maths, english, french 
を与えるだろう

英語を勉強する学生の数を数えることは、Magentoが自動的に部分を使用する私の最初の質問の。カウントについては、次のように元のクエリを変更します。

  1. 選択されている列を削除します。これはnameclassesの列になります。
  2. 選択するために、count(*)列が

この肉屋の後、上記の私のクエリは私に在籍生徒数を与えることはありません

SELECT COUNT(*) 
FROM students LEFT JOIN enrolments ON students.id=enrolments.student_id 
WHERE students.id IN (SELECT e.student_id 
         FROM enrolments AS e 
         WHERE e.class LIKE "english") 

なっいかなるgroup by句を削除し追加します私が必要とする英語コース。代わりに、英語コースに登録しているすべての生徒の合計登録数を教えてくれます。

私は両方のコンテキスト、カウント、および行の取得に使用できるクエリを考え出しています。私はどのような節や節を残すことができます。

答えて

1

元のクエリの問題はGROUP BY句です。各ユーザのクラスの数を二列につながるGROUP BY句を保つことによってCOUNT(*)を選択:

| COUNT(*) | 
|----------| 
|  2 | 
|  3 | 

GROUP BY句を削除すると、ちょうど、LEFT JOINからすべての行数をretunます:

| COUNT(*) | 
|----------| 
|  5 | 

私が見る唯一の方法では、magentoは元のクエリをサブクエリ(派生テーブル)に置き、結果の行を数えます。しかし、それは恐ろしいパフォーマンスに終わるかもしれません。私はGROUP BY句を持つクエリをページネーション(またはそのようなもの)に使用することはできないという不平を言って例外もあります。予期せぬ結果を返すだけで、おそらくライブラリができることは最悪です。

:-)

Well, it just so happens I have a solution.は、SELECT句でGROUP_CONCATためcorelatedサブクエリを使用してください。この方法では、GROUP BY句は必要ありません。

SELECT name, (SELECT GROUP_CONCAT(enrolments.class) 
       FROM enrolments 
       WHERE enrolments.student_id = students.id 
     ) AS classes 
FROM students 
WHERE students.id IN (SELECT e.student_id 
         FROM enrolments AS e 
         WHERE e.class LIKE "english") 

しかし、私はINNERではなく、IN条件のJOINを使用するクエリを書き直します:

SELECT s.name, (
    SELECT GROUP_CONCAT(e2.class) 
    FROM enrolments e2 
    WHERE e2.student_id = s.id 
) AS classes 
FROM students s 
JOIN enrolments e1 
    ON e1.student_id = s.id 
WHERE e1.class = "english"; 

両方のクエリは、あなたのオリジナルのものと同じ結果を返します。

| name | classes    | 
|-------|----------------------| 
| paul | biology,english  | 
| james | maths,english,french | 

また、私のマゼンタを修正したときに正しいカウントを返します。

| COUNT(*) | 
|----------| 
|  2 | 

デモ:http://rextester.com/OJRU38109

さらに - チャンスはそれも原因しばしば参加し、GROUP BYを持つクエリの悪い実行計画を作成し、MySQLsオプティマイザに、よりよく機能することをいいます。

+0

残念ながら、前述のとおり、Magentoはカウントクエリを作成する前に列を削除します。つまり、相関サブクエリが削除されます。試してくれてありがとう。 – Dom

+0

Magentoの構造を操作するために、選択された列からサブクエリをジョインにシフトすることでクエリを作成できます。ただし、外部表の各反復でサブクエリが実行されるため、これは実際には遅いです。 – Dom

+0

"残念ながら、私が言及したように、Magentoはカウントクエリを作成する前に列を削除します" - はい。そして、カウントは私のクエリの行数と同じになります。だから問題は何ですか? –

関連する問題