0

変数がmysqlでどのように機能するかについて疑問があります。私が彼らのウェブで読んだように、変数を設定すると次の行に表示されるようになります。

私のテーブルは次のようなものです:

A     B     C      N
1    NULL   NULL   4
1    NULL   NULL   4 
1     1     NULL   4 
1     1     NULL   4
1     1     1      4
1     1     1      4

私が欲しいのは、の行のみを返すことですC = 1。行がない場合は、行がない場合を返しB = 1 and C is NULLますA = 1 and B is NULL and C is NULL

私の考えは:

select N as number,
       @var_c := case when (C = 1) then 1 else -1 end as myc,
       @var_b := case when (@var_c < 0 and B = 1) then 1 else -1 end as myB,
       @var_c := case when (@var_a < 0 and var_b < 0 and C = 1) then 1 else -1 end as myC

from (select @var_a := -1) r_a,
     (select @var_b := -1) r_b,
     (select @var_c := -1) r_c,
     (select A, B, C, N from my_table order by A desc, B desc, C desc) rows

返すべき(返したい)

number     myA    myB    myC
  4         -1      -1    1
  4         -1      -1    1
  4         -1      -1    -1
  4         -1      -1    -1
  4         -1      -1    -1
  4         -1      -1    -1

これで動作しhaving myA > 0 or myB > 0 or myC > 0ます。

しかし、それは戻ってきています

number    myA     myB    myC
  4         1      -1    -1
  4         1      -1    -1
  4         -1      -1    1
  4         -1      -1    1
  4         -1      1    -1
  4         -1      1    -1

Mysql は行全体で変数を保持するべきではありませんか?

よろしく。

4

2 に答える 2

1

まず、このような変数は使用しないでください。FROM句に変数を設定してから、句の値にアクセスできるとは思わないでくださいSELECT。それは変数の仕組みではありません。通常、変数はクエリ内の 1 か所でのみ使用する必要があります。そうしないと、不確定な結果が得られる可能性があります。

次に、3 つの異なるクエリを発行してみませんか? 最初に のA = 1 and B is NULL and C is NULL場合、行が返されない場合は、2 番目の条件を設定してクエリを発行します。などなど。

そして、最終的に単一のクエリだけを発行したい場合は、これを試すことができます:

SELECT N as number
FROM my_table
WHERE IF(EXISTS (SELECT A FROM my_table WHERE A = 1 and B is NULL and C is NULL),
    A = 1 and B is NULL and C is NULL,
    IF(EXISTS (SELECT A FROM my_table WHERE B = 1 and C is NULL), B = 1 and C is NULL, C = 1))

しかし、それはパフォーマンスを損なう可能性が非常に高いです。したがって、1 つではなく 3 つのクエリを使用することをお勧めします。

UPD:別の(まだ似ている)アプローチがあります:

SELECT N as number
FROM my_table
WHERE (
  A = 1
  AND B is NULL
  AND C is NULL
) OR (
  B = 1
  AND C is NULL
  AND NOT EXISTS (SELECT A FROM my_table WHERE A = 1 and B is NULL and C is NULL)
) OR (
  C = 1
  AND NOT EXISTS (SELECT A FROM my_table WHERE A = 1 and B is NULL and C is NULL)
  AND NOT EXISTS (SELECT A FROM my_table WHERE B = 1 and C is NULL)
)
于 2012-04-26T15:36:58.927 に答える
0

他のサンプルとそのコメントから、この方法でクエリにアプローチします。"C = 1" 値が存在する場合に事前に修飾し、CCnt フィールドに格納する最初のクエリ。見つからない場合は、CCnt 値を強制的に NULL にします。2 番目に、「B」列に対して同じ操作を行います。これらはそれぞれ制限が 1 であるため、それぞれ C=1 または B=1 のエントリを見つけることができる限り、高速である必要があります。そうでない場合、それらの値は NULL です。なぜこのようにするのですか?クエリは、クエリの実行ごとに 1 回実行され、回答が完了します。サブクエリとして使用すると、パフォーマンスが大幅に向上する可能性があるため、クエリを繰り返し実行し続ける必要はありません。group by なしで count() を実行すると、単一の行として保証されるため、重複を引き起こす可能性のあるデカルトの結果はありません。

このプリエンプティブ クエリが完了したので、メイン テーブルに追加します。この時点で、「HasCEntry.CCnt」の値は 1 または NULL になります。「HasBEntry.CCnt」の値は 1 または NULL になります。

select 
      YT.*
   from
      ( select IF( count(*) > 0, 1, NULL ) as CCnt
           from YourTable
           where C = 1
           limit 1 ) HasCEntry,
      ( select IF( count(*) > 0, 1, NULL ) as BCnt
           from YourTable
           where B = 1
           limit 1 ) HasBEntry,
      YourTable YT
   where
            YT.C = 1
      OR  ( YT.B = 1 AND HasCEntry.CCnt IS NULL )
      OR  ( YT.A = 1 AND HasBEntry.BCnt IS NULL AND HasCEntry.CCnt IS NULL )

さて、WHERE句に続きます。C=1 のレコードが 1 つでもある場合、必要なのは YT.C = 1 だけで、それで完了です... 気にしない他の「OR」条件があれば、そのレコードは順調に進んでいます。

ここで、C = 1 のエントリがないとします。「CCnt」値が NULL であることがわかっているため、最初の「OR」条件に入り、「B」に対してテストされます... B 具体的には = 1 AND CCnt IS NULL... したがって、「C=2」(3、4、またはその他の値) のエントリがあった場合、それは必要ありません。B = 1 AND C = NULL のみが必要です...

C と B が失敗した場合、「A」テストに入ります。同様に、上記の B と同じ理由で、A = 1 AND B は null AND C です。

小さなテーブルの場合、Shedal の回答とパフォーマンスに大きな違いがあることに気付かないかもしれません。ただし、テーブルが大きくなるにつれて、大ヒットになる可能性があります。

于 2012-04-28T21:44:19.367 に答える