2017-04-22 11 views
0

誰でもこのクエリーに間違いがあることを知っていますか?メジャーNOT INが機能していないSQLクエリー

これは自分自身で完璧に動作します:

SELECT * FROM 
(SELECT * FROM data WHERE site = '".$id."' 
AND disabled = '0' 
AND carvotes NOT LIKE '0' 
AND (time > (now() - INTERVAL 14 DAY)) 
GROUP BY car ORDER BY carvotes DESC LIMIT 0 , 10) 
X order by time DESC 

だから、このことを行います。

SELECT * FROM data WHERE site = '".$id."' AND disabled = '0' GROUP BY car DESC ORDER BY time desc LIMIT 0 , 30 

しかし、このようにそれらを組み合わせる:

SELECT * FROM data WHERE site = '".$id."' AND disabled = '0' AND car NOT IN (SELECT * FROM 
    (SELECT * FROM data WHERE site = '".$id."' 
    AND disabled = '0' 
    AND carvotes NOT LIKE '0' 
    AND (time > (now() - INTERVAL 14 DAY)) 
    GROUP BY car ORDER BY carvotes DESC LIMIT 0 , 10) 
    X order by time DESC) GROUP BY car DESC ORDER BY time desc LIMIT 0 , 30 

は、エラーが発生します。何か案は?

+0

phpmyadminでこのクエリを実行できますか?あなたが期待している結果は何ですか? – Muntasir

+0

動作しません。 #1241 - オペランドには1つの列が含まれている必要があります。私は、最初のクエリ(NOT IN)の部分にないすべての車を取得して、それらを以下のリストに表示できるようにすることを期待しています。 – binnathon

+0

'....車ではありません(SELECT * FROM ......' 'SELECT *'を 'SELECT car 'に変更する – Muntasir

答えて

1

あなたの問題の主な原因はcar NOT IN (SELECT * FROM (SELECT *で...あなたがサブクエリから返された各行でcarの各レコードの値を比較しようとしているということです...

$result = mysqli_query($con, 
         "SELECT * 
         FROM data 
         WHERE site = '" . $id . 
         "' AND disabled = '0' 
          AND car NOT IN (SELECT car 
              FROM (SELECT car, 
                  carvotes 
                FROM data 
                WHERE site = '" . $id . 
                "' AND disabled = '0' 
                 AND carvotes NOT LIKE '0' 
                 AND (time > (NOW() - INTERVAL 14 DAY)) 
                GROUP BY car 
                ORDER BY carvotes DESC 
                LIMIT 10) X 
              ) 
         GROUP BY car 
         ORDER BY time DESC 
         LIMIT 30"); 

を次のことを試してみてください。 INでは、比較の両側に同じ数のフィールドが必要です。サブクエリの両方のレベルでSELECT *を使用することによって、比較の右側に多くのフィールドがあることを確認していましたが、左側の単一フィールドと比較して多くのフィールドがdataであるため、MySQLが混乱していました。

単一のフィールド、つまりcarと比較することを目指しているので、私たちのサブクエリーはそのデータセットからcarフィールドだけを選択する必要があります。サブクエリの結果のソート順は、INの比較には影響しないため、最も内側のクエリはcarを返しているので、サブクエリの外部レベルを削除しました。

サブクエリの最初の部分をSELECT carに変更する以外に、サブクエリに加えた変更は、LIMIT 0, 10LIMIT 10に変更することだけです。前者は、最初のレコードから0によってオフセットされたレコードを10に制限しています。これは、615にしたい場合に便利ですが、1から10の場合はLIMIT 10と同じ効果があり、少しシンプルです。あなたの全体的なステートメントの最後にLIMIT 0, 30のDitto。

ステートメント本体については、要件/環境設定が何であるかを示すステートメントが作成されていないため、返されるフィールド(またはフィールドの集約関数)を指定する試みは一切行っていません。 GROUP BYがまだ有効な値のセットを残していることに満足していれば、そのすべてが有効ですが、そうでない場合は、その詳細について具体的に質問を書き直すことをおすすめします。

デフォルトでは、MySQLはGROUP BYのデータを昇順にソートしますが、ORDER BY句も存在する場合は、GROUP BYのソートパターンを上書きします。したがって、GROUP BY car句のいずれかの後にDESCを指定すると効果がありません。したがって、発生箇所を削除しました。

興味深い傍点:GROUP BYの並べ替えは、ORDER BY NULLを指定して上書きできます。

ご不明な点がございましたら、お気軽にコメントを投稿してください。

さらに読書

https://dev.mysql.com/doc/refman/5.7/en/order-by-optimization.htmlからSELECT文の構文に - - 特にパーツをLIMITをどうする

https://dev.mysql.com/doc/refman/5.7/en/select.htmlソートあなたのORDER BYの最適化に関する。

https://www.w3schools.com/php/php_mysql_select_limit.aspからLIMIT

+0

これは完璧に動作します。ありがとうございます:) – binnathon

+0

私は私の説明を調べている途中です。しかし、これが実際にあなたの質問に対する回答であることに満足していて、それが利用可能な回答の中で最も有益な回答であると思われる場合は、回答の上にあるチェックマークをクリックして受け入れることができます。回答を受け入れると回答者は15ポイントで報酬を得て、StackOverflowの回答のない質問から質問を削除します。 – toonice

0

クエリ自体は特にうまく設計されていないように見えるので、必要なものを正確に定義しようとする場合があります。

しかし、2点 - あなたの最初の「not」は車の値と*を一致させようとすると、(SELECT * FROM data WHERE site = '".$id."'はおそらく(SELECT car FROM data WHERE site = '".$id."'であるはずです。

また、私はcarvotes NOT LIKE '0'の点を見ていません。この単純な場合は、0と等しいではないcarvotesの場合です。carvotes != '0'に簡略化してください。

+0

あなたの回答の質を向上させるには、 – toonice

1

の単純な説明これはあなたのクエリです:

SELECT * 
FROM data 
WHERE site = '".$id."' AND disabled = '0' AND 
     car NOT IN (SELECT * 
        FROM (SELECT * 
         FROM data 
         WHERE site = '".$id."' AND 
           disabled = '0' AND 
           carvotes NOT LIKE '0' AND 
           (time > (now() - INTERVAL 14 DAY)) 
         GROUP BY car 
         ORDER BY carvotes DESC 
         LIMIT 0 , 10 
         ) x 
        ORDER BY time DESC 
       ) 
GROUP BY car DESC 
ORDER BY time desc 
LIMIT 0 , 30 ; 

いくつかのコメント:

  • は、単一引用符で整数定数をラップしないでください。これは人々を誤解させる可能性があります。これはオプティマイザを誤解させる可能性があります。
  • 整数に文字列関数を使用しないでください(likeなど)。同じ理由。
  • NOT INサブクエリを使用すると危険です。この構成では、期待通りにNULLの値が処理されません。代わりにNOT EXISTSまたはLEFT JOINを使用してください。
  • サブクエリを使用する場合、ORDER BYはほとんど適切ではありません。
  • SELECT *GROUP BYと使用しないでください。それは間違っているだけです。また

    SELECT d.car, MAX(time) as time 
    FROM data d LEFT JOIN 
        (SELECT d2.* 
         FROM data d2 
         WHERE d2.site = '".$id."' AND 
          d2.disabled = 0 AND 
          d2.carvotes NOT LIKE 0 AND 
          (d2.time > (now() - INTERVAL 14 DAY)) 
         GROUP BY d2.car 
         ORDER BY carvotes DESC 
         LIMIT 0 , 10 
        ) car10 
        ON d.car = car10.car 
    WHERE d.site = '".$id."' AND d.disabled = 0' AND 
         car10.car IS NOT NULL 
    GROUP BY car DESC 
    ORDER BY MAX(time) desc 
    LIMIT 0 , 30 ; 
    

    SELECT *を使用してGROUP BY中を削除します。幸い、MySQLの5.7だから、このアンチパターン

を拒否するために、そのデフォルトを変更しました、このクエリを記述するより良い方法は、このようなものです外側のクエリ

関連する問題