3

次の2つのリクエストの違いを誰でも説明できますか:

SET @foundnow=0;
SELECT id, (@foundnow:=IF(`id`=3,1,0)) as ff
FROM `sometable` 
HAVING @foundnow=0
                                  result is
id  ff
1   0
2   0
3   1

SET @foundnow=0;
SELECT id, (@foundnow:=IF(`id`=3,1,0)) as ff
FROM `sometable` 
HAVING ff=0
                                  result is
id  ff
1   0
2   0
4   0
5   0
...

最初に id=3 (含む) までのすべての行を指定し、次に id=3 を除くすべての行を指定するのはなぜですか?

この質問に関連しているのは、次のリクエストの「予期しない」動作だと思います

SET @tot=0;
SELECT @tot:=@tot+1 as `ff`
FROM `anytable`
HAVING (`ff`>10)

これにより、ff=12,14,16,18... の行が得られます。

4

1 に答える 1

1

@foundnow行ごとの変数ではありません。それは生き続けます。列を作成ffすると、行ごとの値になります。また、ドキュメントから:

SELECT ステートメントでは、各選択式はクライアントに送信されたときにのみ評価されます。これは、HAVING、GROUP BY、または ORDER BY 句で、select 式リストの値が割り当てられている変数を参照すると、期待どおりに機能しないことを意味します。

つまり、最初の例は次のようになります。

  • 1: @foundrow が必要、それは 0 なので、送信、@foundrow を新しい値 (0) に設定
  • 2: @foundrow が必要です。0 ですので、送信し、@foundrow を新しい値 (0) に設定します。
  • 3: @foundrow が必要、0 なので送信、@foundrow を新しい値に設定 (1)
  • 3: @foundrow が必要です。1 です。送信しないでください
  • 4: @foundrow が必要です。1 です。送信しないでください
  • 5: @foundrow が必要です。1 です。送信しないでください
  • 等...

そして、あなたの2番目は次のようになります:

  • 1: ff が必要、select を実行、@foundrow を設定、ff を設定 (=もはや @foundrow ではない) = 送信
  • 2: ff が必要で、select を実行し、@foundrow を設定し、ff を設定 (= @foundrow ではなくなった) = send
  • 3: ff が必要、select を実行、@foundrow を設定、ff を設定 (=もはや @foundrow ではない) = 送信しない
  • 4: ff が必要、select を実行、@foundrow を設定、ff を設定 (=もはや @foundrow ではない) = 送信

したがって、@foundrow!=0 の場合、最初の例は式をまったく評価しません。これは、@foundrow が既知であり、MySQL がその選択式の内容を気にしないためです。2 つ目は結果セット内の列を参照するため、その結果を知る必要があり、選択を実行します。

HAVINGまた、を使用できる場合は、できるだけ節WHEREを避けください。

于 2012-12-11T19:32:41.400 に答える