加入收藏 | 设为首页 | 会员中心 | 我要投稿 湖南网 (https://www.hunanwang.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程 > 正文

sql – 按照差异表中的列从SELECT中删除行

发布时间:2021-04-02 05:28:19 所属栏目:编程 来源:网络整理
导读:我正在探求一种要领来按照另一个表的行中的某些值从一个表的SELECT中过滤掉行. 我正在实行下面的示例布局.我有一个博客文章内容表(每篇博文一行),另一个关于帖子的元数据表(每个键值对一行;每行有一个列与博客文章关联;每行多行博客文章).我想只在元数据中没

我正在探求一种要领来按照另一个表的行中的某些值从一个表的SELECT中过滤掉行.

我正在实行下面的示例布局.我有一个博客文章内容表(每篇博文一行),另一个关于帖子的元数据表(每个键值对一行;每行有一个列与博客文章关联;每行多行博客文章).我想只在元数据中没有行的环境下拉一行帖子,个中metadata.pid = posts.pid AND metadata.k =’optout’.也就是说,对付下面的示例布局,我只想回到posts.id = 1行.

(按照我的实行)JOIN最终不会删除有一些元数据的帖子,个中metadata.k =’optout’,由于该pid的另一行元数据意味着它会进入功效.

mysql> select * from posts;
+-----+-------+--------------+
| pid | title | content      |
+-----+-------+--------------+
|   1 | Foo   | Some content |
|   2 | Bar   | More content |
|   3 | Baz   | Something    |
+-----+-------+--------------+
3 rows in set (0.00 sec)

mysql> select * from metadata;
+------+-----+--------+-----------+
| mdid | pid | k      | v         |
+------+-----+--------+-----------+
|    1 |   1 | date   | yesterday |
|    2 |   1 | thumb  | img.jpg   |
|    3 |   2 | date   | today     |
|    4 |   2 | optout | true      |
|    5 |   3 | date   | tomorrow  |
|    6 |   3 | optout | true      |
+------+-----+--------+-----------+
6 rows in set (0.00 sec)

子查询可以给我与我想要的相反:

mysql> select posts.* from posts where pid = any (select pid from metadata where k = 'optout');
+-----+-------+--------------+
| pid | title | content      |
+-----+-------+--------------+
|   2 | Bar   | More content |
|   3 | Baz   | Something    |
+-----+-------+--------------+
2 rows in set (0.00 sec)

…可是行使pid!= any(…)给了我帖子中的全部3行,由于每个pid都有一个元数据行,个中k!=’optout’. 最佳谜底 听起来你想要做LEFT JOIN,然后搜查毗连表的值为NULL的功效,表白没有这样的毗连记录.

譬喻:

SELECT * FROM posts 
LEFT JOIN metadata ON (posts.pid = metadata.pid AND metadata.k = 'optout')
WHERE metadata.mdid IS NULL;

这将从表格帖子中选择任何没有响应元数据行且值为k =’optout’的行.

编辑:值得留意的是,这是左毗连的要害属性,不合用于通例毗连;纵然毗连表中不存在匹配值,左毗连也将始终返回第一个表中的值,从而应承您按照穷乏这些行执行选择.

编辑2:让我们澄清这里关于LEFT JOIN和JOIN(为了清楚起见我称之为INNER JOIN但在MySQL中可交流)的环境.

假设您运行以下两个查询之一:

SELECT posts.*,metadata.mdid,metadata.k,metadata.v 
FROM posts 
INNER JOIN metadata ON posts.pid = metadata.pid;

要么

SELECT posts.*,metadata.v 
FROM posts 
LEFT JOIN metadata ON posts.pid = metadata.pid;

两个查询都天生以下功效集:

+-----+-------+--------------+------+-------+-----------+
| pid | title | content      | mdid | k     | v         |
+-----+-------+--------------+------+-------+-----------+
|   1 | Foo   | Some content |    1 | date  | yesterday |
|   1 | Foo   | Some content |    2 | thumb | img.jpg   |
+-----+-------+--------------+------+-------+-----------+

此刻,让我们假设我们修改查询以添加提到的“optout”的特殊前提.起首,INNER JOIN:

SELECT posts.*,metadata.v 
FROM posts 
INNER JOIN metadata ON (posts.pid = metadata.pid AND metadata.k = "optout");

正如所料,这不会返回任何功效:

Empty set (0.00 sec)

此刻,将其变动为LEFT JOIN:

SELECT posts.*,metadata.v 
FROM posts 
LEFT JOIN metadata ON (posts.pid = metadata.pid AND metadata.k = "optout");

这会发生一个功效集:

+-----+-------+--------------+------+------+------+
| pid | title | content      | mdid | k    | v    |
+-----+-------+--------------+------+------+------+
|   1 | Foo   | Some content | NULL | NULL | NULL |
+-----+-------+--------------+------+------+------+

INNER JOIN和LEFT JOIN之间的区别在于,假如来自BOTH联接表的行匹配,则INNER JOIN将仅返回功效.在LEFT JOIN中,无论是否找到任何要插手的内容,都将始终返回第一个表中匹配的行.在许多环境下,行使哪一个并不重要,但选择正确的一个很是重要,这样才气获自得想不到的功效.

以是在这种环境下,提议查询:

SELECT posts.*,metadata.v 
LEFT JOIN metadata ON (posts.pid = metadata.pid AND metadata.k = 'optout')
WHERE metadata.mdid IS NULL;

将返回与上面沟通的功效集:

+-----+-------+--------------+------+------+------+
| pid | title | content      | mdid | k    | v    |
+-----+-------+--------------+------+------+------+
|   1 | Foo   | Some content | NULL | NULL | NULL |
+-----+-------+--------------+------+------+------+

但愿破除它!插手是一个很好的对象要进修,完全领略何时行使哪一个是一件很是好的工作.

(编辑:湖南网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读