我想知道是否有人可以帮助我为以下逻辑编写一些代码。
我们有一张桌子
----------------
id, lang, letter
----------------
1 1 E
1 1 E
1 1 E
1 1 E
2 2 F
问题:
我需要选择以下条件失败的所有行:
我知道我可以硬编码。另外我想在一个查询中执行此操作。
请帮忙
答案 0 :(得分:3)
WHERE NOT
(
id = lang
AND
(
(lang = 1 AND letter = 'e')
OR (lang = 2 AND letter = '2')
)
)
答案 1 :(得分:1)
select * from table
where id <> lang and
(lang<>1 and letter <> 'e' or
lang<>2 and letter <> '2')
假设您的意思是希望所有这些条件均为假的数据。
答案 2 :(得分: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'
)
)
)
答案 3 :(得分:-1)
这里的想法是有三个业务规则可以实现为三个不同的元组约束(即表中的每一行都不是假的):
id
和lang
必须相等(问问题,为什么不将其作为计算列?)。
如果letter
为'E'
,那么lang
必须为1
(我认为您的问题中有一个拼写错误,而您说的是'e'
'E'
)。
如果letter
为'F'
,那么lang
必须为2
(我认为您的问题中有一个拼写错误,而您说的是2
'F'
)。
对于任何其他数据(例如,当letter
为'X'
时),约束“没有任何说法”,并允许此传递。
所有三个元组约束都可以作为约束验证查询以连接法线形式编写:
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's和double-negative),例如
SELECT * FROM T
WHERE id <> lang
OR ( letter = 'E' AND lang <> 1 )
OR ( letter = 'F' AND lang <> 2 )
从逻辑上讲,对于优化器来说这应该更好,因为对于上面的矛盾,每个析取成员必须是假的(换句话说,它只需要一个OR'ed子句为真,数据被认为是'坏')。在实践中(理论上?),优化器应该能够无论如何都能执行这样的重写!
P.S。空值对逻辑有害 - 避免它们!
这是我的测试代码,包含样本数据:
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 );