1

誰かが私が次のロジックのコードを書くのを手伝ってくれるかどうか疑問に思いました。

テーブルがあります

----------------
id, lang, letter
----------------
1    1      E
1    1      E
1    1      E
1    1      E
2    2      F 

問題:

次の条件が失敗するすべての行を選択する必要があります。

  • id = lang(つまり、1または2のいずれか)
  • lang = 1(文字='e'の場合)またはlang = 2(文字= 2の場合)

私はそれをハードコーディングできることを知っています。また、これは1つのクエリでのみ実行したいと思います。

助けてください

4

4 に答える 4

3
WHERE NOT
(
    id = lang
    AND
    (
        (lang = 1 AND letter = 'e')
        OR (lang = 2 AND letter = '2')
    )
)
于 2012-04-30T18:49:01.793 に答える
1
select * from table
where id <> lang and
(lang<>1 and letter <> 'e' or
lang<>2 and letter <> '2')

これらの条件の両方が偽であるすべてのデータが必要であることを意味すると仮定します。

于 2012-04-30T18:44:41.250 に答える
0

これは、その基準を満たすレコードを除外したいものだと思います。

create table #t
(
    id int,
    lang int,
    letter varchar(1)
)

insert into #t values (1, 1, 'E')
insert into #t values (1, 1, 'E')
insert into #t values (1, 1, 'E')
insert into #t values (1, 1, 'E')
insert into #t values (2, 2, 'F')
insert into #t values (1, 1, 'G')
insert into #t values (1, 1, 'H')
insert into #t values (1, 1, 'I')
insert into #t values (1, 1, 'J')
insert into #t values (2, 2, '2')


SELECT *
FROM #t
WHERE NOT
(
    id = lang
    AND
    (
        (
            lang = 1
            AND letter = 'E'
        )
        OR
        (
            lang = 2
            AND letter = '2'
        )
    )
)

drop table #t

それを含むレコードを取得するには、NOTそれを削除するだけです。

SELECT *
FROM #t
WHERE 
(
    id = lang
    AND
    (
        (
            lang = 1
            AND letter = 'E'
        )
        OR
        (
            lang = 2
            AND letter = '2'
        )
    )
)
于 2012-04-30T18:50:54.133 に答える
-1

ここでの考え方は、3つの異なるタプル制約として実装できる3つのビジネスルールがあるということです(つまり、テーブルのすべての行に対してfalseではありません)。

  1. id等しくなければなりlangません(論点先取、計算列を作成してみませんか?)。

  2. もしそうなら、そうletterでなければ'E'なりlangません1(私はあなたの質問にあなたが'e'代わりに言ったタイプミスがあると思います'E')。

  3. もしそうなら、そうletterでなければ'F'なりlangません2(私はあなたの質問にあなたが2代わりに言ったタイプミスがあると思います'F')。

制約は、他のデータについて「何も言うことはありません」(たとえば、いつletterであるか'X')、これを通過させることができます。

3つのタプル制約はすべて、制約検証クエリとして連言標準形で記述できます。

SELECT * FROM T
 WHERE id = lang
       AND ( letter <> 'E' OR lang = 1 ) 
       AND ( letter <> 'F' OR lang = 2 )

制約に違反するデータは、(疑似関係代数で)次のように簡単に表示できます。

T MINUS (constraint validation query)

SQLの場合:

SELECT * FROM T
EXCEPT
SELECT * FROM T
 WHERE id = lang
       AND ( letter <> 'E' OR lang = 1 ) 
       AND ( letter <> 'F' OR lang = 2 )

選択したクエリが選択したDBMSの接着剤のように実行される場合に備えて、述語を書き直すことができるのは良いことです。上記は、例えばとして書き直すことができます

SELECT * FROM T
 WHERE NOT ( id = lang
            AND ( letter <> 'E' OR lang = 1 ) 
            AND ( letter <> 'F' OR lang = 2 ) )

書き換え法の適用(ド・モルガンの法則と二重否定法)eg

SELECT * FROM T
 WHERE id <> lang
       OR ( letter = 'E' AND lang <> 1 ) 
       OR ( letter = 'F' AND lang <> 2 ) 

論理的に言えば、これはオプティマイザーにとってより良いはずです。なぜなら、上記が矛盾するためには、すべての分離メンバーが偽でなければならないからです(言い換えると、データが「悪い」と見なされるには、1つのOR'ed句だけが真になります) 。実際には(理論的には?)、オプティマイザーはとにかくそのような書き換えを実行できるはずです!

ps nullは論理に悪いです-それらを避けてください!


サンプルデータを含む私のテストコードは次のとおりです。

WITH Nums AS ( SELECT * 
                 FROM ( VALUES (0), (1), (2) ) AS T (c) ), 
     Chars AS ( SELECT * 
                  FROM ( VALUES ('E'), ('F'), ('X') ) AS T (c) ), 
     T AS ( SELECT N1.c AS id, N2.c AS lang, 
                   C1.c AS letter
              FROM Nums AS N1, Nums AS N2, Chars AS C1 )

SELECT * FROM T
EXCEPT
SELECT * FROM T
 WHERE id = lang
       AND ( letter <> 'E' OR lang = 1 ) 
       AND ( letter <> 'F' OR lang = 2 );
于 2012-04-30T23:39:22.470 に答える