sql - 需要使用 group by 和 having 子句验证一致的结果集
问题描述
我有一张如下表
CREATE TABLE `zpost` (
`post_id` int(10) UNSIGNED NOT NULL,
`topic_id` int(10) UNSIGNED NOT NULL DEFAULT 0,
`post_subject` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
数据集为
INSERT INTO `zpost` (`post_id`, `topic_id`, `post_subject`) VALUES
(44, 33, 'New topic by new user'),
(45, 33, 'Re: New topic by new user'),
(47, 33, 'Re: New topic by new user'),
(46, 34, 'New Topic by James on 1/2'),
(48, 35, 'Sep 29th new topic'),
(49, 35, 'Re: Sep 29th new topic'),
(50, 35, 'Re: Sep 29th new topic'),
(51, 36, 'Another Sep topic');
和索引(与问题无关,但在这里)
ALTER TABLE `zpost`
ADD PRIMARY KEY (`post_id`),
ADD KEY `topic_id` (`topic_id`);
最后是 SQL
SELECT * FROM `zpost` group by `topic_id` having min(`topic_id`);
最后输出
|post_id|topic_id|post_subject |
+-------+--------+--------------------------+
| 44| 33|New topic by new user |
| 46| 34|New Topic by James on 1/2 |
| 48| 35|Sep 29th new topic |
| 51| 36|Another Sep topic |
我只想要给定 topic_id 的最小 post_id - 第一个主题记录。我似乎默认情况下得到了这一点。不确定这是否只是数据库决定提供行的方式,或者这是否是一致的顺序。有问题的数据库是 MariaDB。我还尝试在数据库中以相反的顺序插入数据,如下所示
INSERT INTO `zpost` (`post_id`, `topic_id`, `post_subject`) VALUES
(51, 36, 'Another Sep topic'),
(50, 35, 'Re: Sep 29th new topic'),
(49, 35, 'Re: Sep 29th new topic'),
(48, 35, 'Sep 29th new topic'),
(46, 34, 'New Topic by James on 1/2'),
(47, 33, 'Re: New topic by new user'),
(45, 33, 'Re: New topic by new user'),
(44, 33, 'New topic by new user');
而且我仍然得到了我想要的结果,这是个好消息,不需要采取进一步的行动。但不确定为什么以及为了完整起见,如果我想要最后一行(最大 post_id),我将如何更改 SQL 以使该行与每个 topic_id 关联?有人会认为将 min 更改为 max 会解决这个问题,但不是!对于这个查询,我也得到了相同的结果。
SELECT * FROM `zpost` group by `topic_id` having max(`topic_id`);
解决方案
首先,在关系数据库中,表中的行没有任何固有的顺序。插入、更新或删除它们的顺序无关紧要。表格代表无序的行包。
您可以使用ROW_NUMBER()
来标识您想要的行。
post_id
要让每个人都变老,topic_id
你可以这样做:
select post_id, topic_id, post_subject
from (
select *, row_number() over(partition by topic_id order by post_id) as rn
from zpost
) x
where rn = 1
结果:
post_id topic_id post_subject
-------- --------- -------------------------
44 33 New topic by new user
46 34 New Topic by James on 1/2
48 35 Sep 29th new topic
51 36 Another Sep topic
请参阅DB Fiddle-ASC上的运行示例。
要获得post_id
每个人的最新信息,topic_id
您可以执行以下操作:
select post_id, topic_id, post_subject
from (
select *, row_number() over(partition by topic_id order by post_id desc) as rn
from zpost
) x
where rn = 1
结果:
post_id topic_id post_subject
-------- --------- -------------------------
47 33 Re: New topic by new user
46 34 New Topic by James on 1/2
50 35 Re: Sep 29th new topic
51 36 Another Sep topic
请参阅DB Fiddle-DESC上的运行示例。
推荐阅读
- sql - 双向复制 SQL Server
- pytorch - 如何优化用于 TensorRT 推理的 grid_sample 的自定义双线性采样替代方案?
- python - 根据布尔条件分配类别
- python - Selenium 在程序中飞来飞去,而不是等待数据出现
- javascript - 隐藏页面 URL,但在 google chrome 的打印页脚中保留页码使用 JavaScript / CSS 打印预览
- c# - 使用 Facebook C# 登录期间收到错误消息“无法加载 URL:此 URL 的域不包含在应用程序的域中”
- android-studio - Android Studio gradle同步每次都失败
- neo4j - 如何在 neo4j 中的 csv 加权图上应用 louvain 算法?
- oracle - cdb 正在连接 Oracle 19c 时无法从 sql developer 连接到 pdb
- haskell - 递归映射函数