3


0

私はあまりSQLをしません、そして、ほとんどの時間、私はCRUD操作をしています。 時折、私はもう少し複雑なことをするでしょう。 だから、この質問は初心者の質問かもしれませんが、私は準備が整いました。 私は何時間もこれを解決しようとしていました、そしてそれは無駄です。

それで、次のテーブル構造を想像してみてください。

> | ID | Col1 | Col2 | Col3 | .. | Col8 |

IDと計算列を選択したい 計算列の範囲は0 - 8で、照会に対する一致数が含まれています。 また、結果セットを制限して、特定の数の一致がある行のみを含めるようにします。

だから、このサンプルデータから:

> | 1 | 'a' | 'b' | 1 | 2 | > | 2 | 'b' | 'c' | 1 | 2 | > | 3 | 'b' | 'c' | 4 | 5 | > | 4 | 'x' | 'x' | 9 | 9 |

Col1 = 'a' OR Col2 = 'c' OR Col3 = 1 OR Col4 = 5で計算結果が1より大きい場合、結果セットは次のようになります。

> | ID |カル| > | 1 | 2 | > | 2 | 2 | > | 3 | 2 |

問題があればT-SQLとSQL Server 2005を使用していますが、DBスキーマを変更することはできません。

私はそれを1つの自己完結型のクエリとして保持し、ストアドプロシージャや一時テーブルを作成する必要がないようにしたいと思います。

3 回答


4


この回答は、CTEを使用して派生テーブルを少しクリーンアップすることで、SQL 2005で機能します。

WITH ASと一致(SELECT ID、Col1 = 'a' 1つの場合0つの場合0終了ケースCol2 = 'c' 1つの場合0終了ケースの場合Col3 = 1 1つのELSE 0終了ケースの場合Col4 = 5つの場合1 ELSE 0の場合Table 1からの結果として終了END1 Col1 = 'a'またはCol2 = 'c'またはCol3 = 1またはCol4 = 5)SELECT ID、結果からの一致WHERE結果> 1


2


これは、ブール比較が整数1または0を返すという事実を利用した解決策です。

SELECT * FROM(SELECT ID、(Col1 = 'a')(Col2 = 'c')(Col3 = 1)(Col4 = 5)ASはMyTableから計算されます)q WHEREは> 1を計算しました。

``は `=`よりも優先順位が高いため、ブール値の比較には括弧で括らなければなりません。 また、通常は同じクエリの `WHERE`句でカラムエイリアスを使用することはできないため、すべてをサブクエリに含める必要があります。

行を制限するためにサブクエリの中で `WHERE`句を使うべきだと思われるかもしれませんが、いずれにせよ全表スキャンを終わらせることになるので、大したことではないでしょう。 一方、そのような制限が副照会の結果の行数を大幅に減らすことを期待しているのであれば、それは価値があります。

'' '' '

Quassnoiのコメントで、ブール式を整数値として扱うことができない場合は、たとえ少し冗長であっても、ブール条件を整数にマップする方法があるはずです。 例えば:

SELECT * FROM(SELECT ID、Col1 = 'a'の場合は1、その他の場合は0
    + CASE WHEN Col2='c' THEN 1 ELSE 0 END
    + CASE WHEN Col3=1   THEN 1 ELSE 0 END
    + CASE WHEN Col4=5   THEN 1 ELSE 0 END AS calculated
MyTableから)qどこで> 1を計算しました。


1


このクエリはよりインデックスフレンドリーです。

SELECT ID、SUM(一致)FROM(SELECT ID、1 ASからmytableへの一致WHERE col1 = 'a' UNIONからの一致WHERE col2 = 'c' UNION ALL SELECT ID、1 ASからのmytableからの一致col3 = 1 UNION ALL SELECT ID、mytableのWHEREから一致するAS 1 col4 = 5)q GROUP BY ID HAVING SUM(match)> 1

これは、検索しているすべての列が最初にインデックス付きで、次に高い基数(多くの異なる値)を持つ場合にのみ効率的になります。

掲載結果の詳細については、私のブログでこの記事を参照してください。