SQL 排除匹配所有多个条件的行
Posted
技术标签:
【中文标题】SQL 排除匹配所有多个条件的行【英文标题】:SQL exclude rows matching all of multiple criteria 【发布时间】:2017-05-21 15:52:07 【问题描述】:我目前有一个合并两个表以创建一个新表进行分析的查询。在尝试绘制图表以进行演示时得到一些有趣的结果后,我了解到其中一些是从未清理过的假数据。我已经能够识别出导致问题的数据,并且为了节省时间,我希望将其排除在查询中,以便继续进行分析。
这个假数据符合所有这些条件:
rate_type = 标准 client_net_cleared = 0 程序为空白(非 Null)我在 SELECT 中使用 CASE 语句标识了这些,但意识到要使用它,我必须执行另一个表,查询该表中的所有内容减去根据 CASE 语句确定为符合上述条件的内容。一定有比这更好的解决方案。
我目前正试图将这些排除在 WHERE 语句中,但阅读了其他问题主题后发现 WHERE 不太擅长管理多个子条件。
我有什么:
SELECT *
, CASE WHEN tad.rate_type = 'Standard'
AND tad.client_net_cleared = '0'
AND program= '' THEN 1
ELSE '0'
END AS noise
FROM tableau.km_tv_ad_data_import tad
JOIN tableau.km_tv_ad_report ga
ON ga.session_timestamp >= tad.timestamp - INTERVAL '4 minute'
AND ga.session_timestamp <= tad.timestamp + INTERVAL '5 minute'
AND ga.session_timestamp != tad.timestamp
WHERE tad.timestamp >= '2016-09-01'
AND (tad.rate_type != 'Standard'
AND tad.client_net_cleared != '0'
AND tad.program != '')
GROUP BY 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21
样本数据集:
timestamp | rate_type | program | client_net_cleared | noise
---------------------|-----------|-----------------|--------------------|-------
2016-11-01 18:00:00 | Standard | Diving | 50 | 0
2016-12-01 21:00:00 | Holiday | Classic Albums | 100 | 0
2016-11-01 09:00:00 | FireSale | Panorama | 0 | 0
2016-10-01 12:00:00 | Standard | | 0 | 1
2016-12-01 15:00:00 | Holiday | MythBusters | 100 | 0
2016-10-01 13:00:00 | FireSale | House | 200 | 0
我需要什么:
排除符合所有三个条件的行:rate_type = Standard、client_net_cleared = 0、program 为空(非 Null)。
【问题讨论】:
你试过嵌套表吗,比如下一个:-select * from ( -- Put your query here ) a where rate_type = Standard and client_net_cleared = 0 and program is not Null
您不能按序号位置分组(至少不能在 sql-server 中)。如果你可以在 mysql 中,这是一个习惯,你应该立即停止。
尤其是在使用SELECT *
时。这使得它依赖于CREATE TABLE
语句中列的顺序。我感觉他实际上是按所有列分组的,所以应该只是SELECT DISTINCT *
。
@SeanLange 有什么更好的分组方式?如果有的话,我很乐意使用更短或更灵活的分组方式!
更好的方法是命名列。如果您更改表(或天堂禁止实际命名列而不是使用 *)并且您按序号位置分组,则您的查询被破坏。修复它变成了一场噩梦。
【参考方案1】:
正确的标准是
AND NOT (tad.rate_type = 'Standard'
AND tad.client_net_cleared = '0'
AND tad.program = '')
deMorgan's Law 相当于:
AND (tad.rate_type != 'Standard'
OR tad.client_net_cleared != '0'
OR tad.program != '')
这与您的查询类似,但请注意它使用的是OR
,而不是AND
。
【讨论】:
但是 OP 说明了所有三个条件都满足的地方......你的第二个陈述否定了这一点,因为只有一个需要等同于真实,或者我错过了什么? @scsimon 请注意,我也否定了标准。这就是德摩根定律:NOT (x AND y)
等价于 (NOT x OR NOT y)
没关系,我现在明白了。谢谢你的教育
@Barmar 这行得通,谢谢!现在我也了解了德摩根定律。【参考方案2】:
您还可以在 WHERE 子句中执行 SELECT 以使用 NOT IN 排除行。例如,一个供应商的所有资格和不在不包括具有其他供应商资格的人:
select * from qualification q
inner join certification c on c.id = q.certificationid
where c.vendorid = 3 and
employeeid not in
(
select employeeid from qualification q
inner join
certification c on c.id = q.certificationid
where c.vendorid <> 3
)
【讨论】:
以上是关于SQL 排除匹配所有多个条件的行的主要内容,如果未能解决你的问题,请参考以下文章