我想建立一个讨论区。因此,我有3个表:t_posts,t_boards,t_board_categories。帖子包含线程(其中post_post_id为NULL)并回复线程(其中post_post_id为非NULL),因此它是自引用的。现在,我想显示所有类别的所有董事会中的最后5个帖子(主题和/或回复)。 sql当前看起来像这样:
SELECT p.post_id,
p.post_board_id,
p.post_user_id,
p2.post_title,
bc.bc_name,
Max(p.post_date) post_date
FROM t_posts p
LEFT JOIN t_posts p2
ON ( p2.post_post_id IS NULL
AND ( p2.post_id = p.post_id
OR p.post_post_id = p2.post_id ) )
LEFT JOIN t_boards b
ON b.board_id = p.post_board_id
LEFT JOIN t_board_categories bc
ON bc.bc_id = b.board_bc_id
WHERE p.post_system_id = '1'
AND p.post_deleted = 0
AND bc.bc_deleted = 0
AND b.board_deleted = 0
GROUP BY p.post_id,
p2.post_id
ORDER BY p2.post_date DESC
LIMIT 5
结果几乎是我想要的,除了,在一个线程中进行多次答复将导致仅显示该线程。我想要的是显示5个不同的线程以及最新的答案,而不仅仅是5个线程。
我加入t_posts p2来显示原始主题。
我还尝试将DISTINCT p2.post_id添加到SELECT中,但是它没有任何改变。
模式:
CREATE TABLE `t_board_categories` (
`bc_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`bc_name` varchar(128) COLLATE utf8_unicode_ci DEFAULT '',
`bc_prio` int(11) NOT NULL DEFAULT '0',
`bc_system_id` int(10) unsigned NOT NULL DEFAULT '0',
`bc_deleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`bc_id`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `t_boards` (
`board_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`board_bc_id` int(10) unsigned DEFAULT NULL,
`board_name` varchar(128) COLLATE utf8_unicode_ci DEFAULT NULL,
`board_subtitle` text COLLATE utf8_unicode_ci,
`board_prio` int(11) NOT NULL DEFAULT '0',
`board_system_id` int(10) unsigned NOT NULL DEFAULT '0',
`board_deleted` tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`board_id`)
) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
CREATE TABLE `t_posts` (
`post_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`post_user_id` bigint(20) unsigned DEFAULT NULL,
`post_title` varchar(128) COLLATE utf8_unicode_ci NOT NULL,
`post_text` text COLLATE utf8_unicode_ci NOT NULL,
`post_post_id` bigint(20) unsigned DEFAULT NULL,
`post_date` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
`post_board_id` int(10) unsigned NOT NULL DEFAULT '0',
`post_system_id` int(10) unsigned NOT NULL DEFAULT '0',
`post_deleted` int(2) NOT NULL DEFAULT '0',
PRIMARY KEY (`post_id`)
) ENGINE=InnoDB AUTO_INCREMENT=205 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
INSERT INTO `t_board_categories` (`bc_id`, `bc_name`, `bc_prio`, `bc_system_id`, `bc_deleted`) VALUES (1, 'Test-Category', '1', '1', '0');
INSERT INTO `t_boards` (`board_id`, `board_bc_id`, `board_name`, `board_subtitle`, `board_prio`, `board_system_id`, `board_deleted`) VALUES (1, '1', 'Test-Board', 'Board Subtitle', '1', '1', '0');
INSERT INTO `t_posts` (`post_id`, `post_user_id`, `post_title`, `post_text`, `post_post_id`, `post_date`, `post_board_id`, `post_system_id`, `post_deleted`) VALUES
(1, 14, 'Thread 1', 'Test1', NULL, '2019-05-22 00:18:25', 1, 1, 0),
(2, 14, 'Thread 2', 'Test2', NULL, '2019-05-22 00:18:44', 1, 1, 0),
(3, 14, 'Thread 3', 'Test 3', NULL, '2019-05-22 00:18:51', 1, 1, 0),
(4, 19, 'Thread 4', 'Test 4', NULL, '2019-05-22 00:19:02', 1, 1, 0),
(5, 19, 'Thread 5', 'Test 5', NULL, '2019-05-22 00:19:07', 1, 1, 0),
(6, 19, 'Thread 6', 'Test 6', NULL, '2019-05-22 00:19:15', 1, 1, 0),
(7, 14, 'Reply', 'A', 5, '2019-05-22 00:19:46', 1, 1, 0),
(8, 14, 'Reply', 'B', 5, '2019-05-22 00:19:47', 1, 1, 0),
(9, 14, 'Reply', 'C', 5, '2019-05-22 00:19:49', 1, 1, 0);
预期结果:线程1-5的一行,带有用户ID和最后答复的日期(线程5的用户ID:14,日期:2019-05-22 00:19:49,线程1-4的最后日期是线程日期,用户ID是线程作者用户ID)
我整个晚上都在工作,很高兴能得到一些帮助。预先谢谢你!
答案 0 :(得分:1)
您的样本数据表明,帖子级别不能超过两个级别(post_post_id
不能是post_post_id
不为空的帖子的ID)。假设,您可以尝试使用相关子查询来获取子帖子和帖子的帖子,按日期降序对其进行排序,并使用LIMIT
来选择顶部的帖子。还要根据最后一个子帖子的降序对主要查询进行排序,并使用LIMIT
来获得前5名。
SELECT bc1.bc_id,
bc1.bc_name,
b1.board_id,
b1.board_name,
p1.post_id,
p1.post_title,
(SELECT p2.post_title
FROM t_posts p2
WHERE p1.post_id IN (p2.post_id,
p2.post_post_id)
ORDER BY p2.post_date DESC
LIMIT 1) last_post_title,
(SELECT p2.post_user_id
FROM t_posts p2
WHERE p1.post_id IN (p2.post_id,
p2.post_post_id)
ORDER BY p2.post_date DESC
LIMIT 1) last_post_user_id,
(SELECT p2.post_date
FROM t_posts p2
WHERE p1.post_id IN (p2.post_id,
p2.post_post_id)
ORDER BY p2.post_date DESC
LIMIT 1) last_post_date
FROM t_posts p1
INNER JOIN t_boards b1
ON b1.board_id = p1.post_board_id
INNER JOIN t_board_categories bc1
ON bc1.bc_id = b1.board_bc_id
WHERE p1.post_post_id IS NULL
ORDER BY last_post_date DESC
LIMIT 5;