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 当 letter = 'e' 或 lang=2 当 letter=2

我知道我可以硬编码。我也想只在一个查询中执行此操作。

请帮忙

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

这里的想法是,可以将三个业务规则实现为三个不同的元组约束(即表中的每一行都不是 false):

  1. id并且lang必须相等(问一个问题,为什么不将其设为计算列?)。

  2. 如果letter是,'E'那么lang必须是1(我假设您说的问题中有错字'e'而不是'E')。

  3. 如果letter是,'F'那么lang必须是2(我假设您说的问题中有错字2而不是'F')。

约束对任何其他数据(例如 when letteris '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 ) )

应用重写定律(德摩根和双重否定),例如

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

从逻辑上讲,这对优化器来说应该更好,因为要使上述矛盾成为矛盾,每个分离成员都必须为假(换句话说,只需一个 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 回答