2017-01-26 13 views
1

私はMicrosoft SQL Server Management Studioで作業しています。私は複数のテーブルを持っており、複数の条件(ほぼ80)が、私が結合されたデータのサブセットを達成しようとしている場所を照会しています。WHERE句のANDおよびORの複数の条件SQL Server

考えられるのは、条件(つまり、NOT IN)に基づいて、そのデータが別の結合ではない結合からデータを取得する必要があるということです。次に、複数の列を含む一連の条件をフィルタリングする必要があります。各列に複数の条件があります。私の問題(私が思う)はORの状態から発生しています。私はcol5というコラムを持っています。もしそれがAND条件の条件を満たさなければ、さらにフィルタリングする必要があります(したがって、ORの条件)。

私がこれまで書いてきたことは、このために、以下、

SELECT 
    handfulOfColumns 
FROM 
    table1 AS t1 
LEFT JOIN 
    (SELECT * 
    FROM table2 
    WHERE col2 = 'thing0' or col2 = 'thing1') AS t2 ON t1.col1 = t2.col1 
WHERE 
    t1.col1 NOT IN (SELECT t1.col1 
        FROM table1 t1 
        LEFT JOIN table3 t3 ON t1.col1 = t3.col1 
        WHERE col3 LIKE '%thing3%') 
    AND (col4 > '#' AND col5 NOT LIKE 'thing4' 
     AND col5 != 'thing5' AND col5 NOT LIKE 'thing6' 
     AND col6 NOT LIKE 'thing7' 
     --... 
     --... add like 20 lines of conditions similar to above 
     --... 
     AND col34 NOT LIKE 'thing77' AND LEN(col35) > '#') 
    OR (col5 NOT LIKE '% %' AND col5 LIKE '%[a-z]%' 
     AND col5 NOT LIKE '%[0-9]%' 
     AND col5 NOT LIKE 'thing209' 
     AND col5 NOT LIKE 'thing210'); 

推論は、私はcol5に取り扱っております(汚い)電話番号の多くを持っている、そして全体的なのがたくさんあるさすべての列でクリーニングを実行します。これらの電話番号の中には、テキストを代わりに入力するものがあります。コンテキストに応じて、それらを保持したりフィルタにかけたりしたい場合があります(電話番号が「ビジネス名」、「ビジネス」、「alskfjalsdkjf」の場合) 「555-5555」や「555 5555」などではなく)。データがAND条件の条件を満たす場合(主にcol5 not like '%555-5555%'のバリエーションを除外)、の数字以外の文字をさらに確認し、フィルタリングする必要があります。これはORです。

エラーメッセージはありません。代わりに、クエリの実行にはかなりの時間がかかり、発生する必要があるデータとは逆のデータが表示されます。 table1table2の構造に基づいて、2つのテーブルを結合することによって重複した行を導入する可能性がありますが、調整やサブセットの量は、あちこち。私のロジックは、このために失敗した場合

私はわからない、任意のヘルプは高く評価され:)

はmarc_sが提案適切な構文の訂正より以外
+0

左結合でサブクエリを修正します。元のものより多くの値が返された場合、そのサブクエリは重複を返します。 – lookslikeanevo

+0

私はちょうどこれの結合部分を実行する場合は、約64K行のデータを取得します(これは、 'table1'だけが約60K行のデータを持つため、重複を含むことになります)。しかし、 'WHERE'節から始まるすべての条件を追加すると、約67K行のデータが得られます。論理的には64K未満で終わるはずです。したがって、重複を考慮しても、予想よりも高い金額を返します。 – rastrast

答えて

0

、これは実際にはうまく動作します。私はいくつかの条件文がAND条件で間違っていたことが分かりました(つまり、いくつかは=で、論理的には!=likeであったはずですがnot likeであったはずです)全体的な構造とロジックは音です。それは完璧に働いています。これが誰かに頭痛を与えた場合の謝罪:)

0

あなたのロジックは、正しい結果を提供してもかなり乱雑に見えます。クエリをより読みやすくするために、私は以下を試してみます:

1)既存のスキーマにいくつかのカラムを追加することができる場合は、クエリで再利用できる意味のあるカラムを追加できます。テーブルは次のようになります。

create table table1 
(
    Id INT NOT NULL, 
    col1 VARCHAR(64), 
    col2 VARCHAR(64), 
    col3 VARCHAR(64), 
    col4 VARCHAR(64), 
    col5 VARCHAR(64), 

    Thing4Like AS (CASE WHEN col4 > '#' AND col5 NOT LIKE 'thing4' THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END) PERSISTED, 
    Thing56 AS (CASE WHEN col5 != 'thing5' AND col5 NOT LIKE 'thing6' THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT) END) PERSISTED 
    -- other columns may come here 
) 

これにより、読みやすいクエリを作成したり、事前に計算された情報があるため、クエリを高速化することができます。また、永続列はインデックスを許可します。

2)スキーマを変更できない場合は、上記のような余分なロジックを含むtable1上のビューを作成できます。余分なパフォーマンスを得るには、indexedにすることができます。

+0

ありがとう!それが働いていても、私が書いたものはかなり厄介であり、改善することができたと思いました。私は比較的SQLを初めて使っていて、最近になって使用し始めたばかりなので、ちょっとしたことをきれいにする方法を常に探しています。 – rastrast

+0

可能であれば、可能な限り読みやすいように書き込んでください。そうでなければ、あなたや同僚は数ヶ月後に何が起こっているのかほとんど理解しません。これは、SQLだけでなく一般的なプログラミングにも当てはまります。 – Alexei