私はこれは、あなたがその基準を満たすレコードを除外したいものだと思いますここで考えているのは、3つの異なるタプル制約として実装できる3つのビジネスルールがあることです(つまり、テーブルのすべての行でfalseではない)。
id
とは等しくなければなりません(なぜなら、計算列を作るのはなぜですか?)。
letter
が'E'
であれば、lang
は1
でなければなりません(私はあなたが'e'
代わりの'E'
言ったあなたの質問にタイプミスがあると仮定します)。
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))
書き直し法(De Morganと二重否定)を適用します。
SELECT * FROM T
WHERE id <> lang
OR (letter = 'E' AND lang <> 1)
OR (letter = 'F' AND lang <> 2)
が論理的に言えば、上記のために、すべての論理和メンバーが偽でなければならない矛盾するので、これは別の言い方をすれば(オプティマイザのために良いはずです、それはデータのみのために真であることが1つの論理和句を取ります「悪い」とみなされる)。実際には(理論的には?)、オプティマイザはであれば、このような書き換えを実行する必要があります。
p.s. nullsは論理に悪いです - それらを避けてください!ここで
は、サンプルデータと私のテストコードです:
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);
あなたの条件には意味がありません。質問を修正してください – Icarus