基于特定条件进行选择

3

如果有人可以更新一下标题,更好地反映我的问题,那就太感激了。我认为我在寻找答案时遇到了困难,因为我不知道正确的搜索术语。

If I have the following values in a table:

TableID      TableSensitivity
-----------------------------
1            aSensitivity
1            aRevision
2            bRevision
3            cRevision
3            cSensitivity

How can I filter the values containing "Revision" only for each TableID where the is already a value containing "Sensitivity". This is the expected output:

TableID      TableSensitivity
-----------------------------
1            aSensitivity
2            bRevision
3            cSensitivity
以下是一个示例设置:
DECLARE  @Example TABLE (TableID INT, TableSensitivity VARCHAR(200))

INSERT INTO @Example(TableID, TableSensitivity) VALUES (1, 'aSensitivity')
INSERT INTO @Example(TableID, TableSensitivity) VALUES (1, 'aRevision')
INSERT INTO @Example(TableID, TableSensitivity) VALUES (2, 'bRevision')
INSERT INTO @Example(TableID, TableSensitivity) VALUES (3, 'cSensitivity')
INSERT INTO @Example(TableID, TableSensitivity) VALUES (3, 'cRevision')

我尝试使用CASE语句来确定具有敏感信息的行,并想到可以使用MAX函数进行过滤,但无法使其正常工作:

SELECT TableID
     , TableSensitivity
     , CASE WHEN TableSensitivity LIKE '%Sensitivity' THEN 1 ELSE 0 END 'SomeKey' 
FROM @Example

你使用的是哪种关系型数据库管理系统?看起来像是SQL Server。请标注一下。 - SS_DBA
@WEI_DBA,谢谢 -- 完成 - CallumDA
我会尝试将 TableSensitivity 拆分为两列。第一列是第一个字母,第二列是其余部分。然后您可以控制分组并搜索敏感度。 - SS_DBA
只是为了澄清,在“Sensitivity”或“Revision”之前只有一个字母的情况下(即“a”,“b”,“c”),实际情况是在之前有可变数量的字母。 - CallumDA
好的,但是那些关键字之前的字母也有意义,理论上可以拆分出来以获得更好的控制。 - SS_DBA
这是一个很好的观点。谢谢 @WEI_DBA - CallumDA
4个回答

3
你可以使用 WHERE NOT EXISTS
SELECT TableID
     , TableSensitivity
FROM @Example e1
WHERE NOT EXISTS
(
    SELECT *
    FROM @Example e2
    WHERE e1.TableID=e2.TableID
    AND e2.TableSensitivity LIKE '%Sensitivity'
    AND e1.TableSensitivity LIKE '%Revision'
)

谢谢你,这正是我所需要的输出。现在我只需要阅读一下 WHERE NOT EXISTS :) - CallumDA

2
这将清除@Example中的行并返回您期望的结果。如果需要,可以修改并将其纳入您的查询中。"最初的回答"。
DELETE
FROM    @Example
WHERE   TableID IN
        (
            SELECT  TableID
            FROM    @Example
            WHERE   TableSensitivity LIKE '%Sensitivity%'
        )
        AND TableSensitivity LIKE '%Revision%'

SELECT  *
FROM    @Example

1
问题表明,原帖作者确实想要一个 SELECT(鉴于这是问题中的示例代码)。 - Gordon Linoff
嗯,你可以争辩说OP确实说了“删除”而不是“过滤”。 :-) - SS_DBA
当我发布我的回复时(以及现在),问题陈述为“如何删除值...”,这就是使用DELETE的原因。 - Junc Mayl
抱歉造成困惑,我之前说了“删除”这个词,没有意识到其含义。理想情况下应该使用SELECT语句,但非常感谢您提供的解决方案 -- 如果我将我的值放入表变量中,它也能起到作用。 - CallumDA

1

这也可以通过使用FIRST_VALUE函数来实现(适用于SQL Server 2012及以上版本)

SELECT DISTINCT 
    TableID, 
    FIRST_VALUE(TableSensitivity) OVER (PARTITION BY TableID ORDER BY 
            CASE WHEN  TableSensitivity LIKE '%Sensitivity' THEN 1 
            WHEN TableSensitivity LIKE '%Revision' THEN 2 
            ELSE 3 END) as TableSensitivity
FROM @Example

0

起初,我完全误解了这个问题。我明白了,你想要一个优先级查询。一个简单的方法是:

select e.*
from @example e
where e.TableSensitivity like '%Sensitivity'
union all
select e.*
from @example e
where e.TableSensitivity like '%Revision' and
      not exists (select 1
                  from @example e2
                  where e2.tableId = e.tableId and
                        e2.TableSensitivity like '%Sensitivity'
                 );

一个更通用的方法是使用row_number()函数:
select e.*
from (select e.*,
             row_number() over (partition by tableId
                                order by case when e.TableSensitivity like '%Sensitivity' then 1 when e.TableSensitivity like '% Revision' then 2 else 3 end
                               ) as seqnum
      from @example e
     ) e
where seqnum = 1;

两个查询都没有得到预期的输出。 - Simon
在第一个查询中,将Having语句中的AND改为OR。这样应该就可以修复第一个查询了。 - SS_DBA
第二个查询块返回表中的所有条目。 - Arulkumar
@Simon...我真的误解了这个问题。奇怪的是,我认为其他答案并没有最好的解决方案,所以我编辑了答案而不是删除它。 - Gordon Linoff

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接