3

我有 2 张桌子,posts并且posts_flags. posts包含用户发表的帖子行。现在,如果某个帖子被举报,用户可以举报该帖子,从而在posts_flags表格中创建一个标志。所以基本上,posts_flags同一个帖子可以有多个标志。

现在,我要做的是posts从表中获取行posts并添加一列以显示已标记的列。为了获得该专栏,我正在尝试使用postsposts_flags使用post_id. 但是,我现在遇到了一个问题,因为posts_flags同一个帖子可以有多行。

我怎样才能得到这些数据?下面是我的表格的示例结构以及我想要实现的目标。

帖子表

| post_id | post_title | post_body |
|    1    |   title a  | something |
|    2    |   title b  | something |
|    3    |   title c  | something |

post_flags 表

| post_id | user_id |
|    1    |   4     | 
|    1    |   5     | 
|    2    |   5     | 

我想要达到的目标

|  post_id | post_title | post_body | flagged
|    1     | title a    | something |   1
|    2     | title b    | something |   1
|    3     | title c    | something |   0

谢谢!

4

3 回答 3

4

与其加入整个表,不如加入一个子查询,每个帖子 ID 只返回 1 行。

它还需要是 aLEFT JOIN而不是INNER JOIN,因此结果将包含没有标志的帖子的行。

SELECT p.*, pf.post_id IS NOT NULL AS flagged
FROM posts AS p
LEFT JOIN (
    SELECT DISTINCT post_id
    FROM posts_flags) AS pf ON p.post_id = pf.post_id
于 2019-09-09T19:27:19.833 回答
2

您可以使用内联子查询来检查当前帖子是否被标记,例如:

SELECT
    p.*,
    CASE WHEN EXISTS (
        SELECT 1 FROM posts_flags pf WHERE pf.post_id = p.post_id
    ) THEN 1 ELSE 0 END flagged
FROM posts p

或者更好:

SELECT
    p.*,
    EXISTS (SELECT 1 FROM posts_flags pf WHERE pf.post_id = p.post_id) flagged
FROM posts p

DB Fiddle 上的演示

| post_id | post_title | post_body | flagged |
| ------- | ---------- | --------- | ------- |
| 1       | title a    | something | 1       |
| 2       | title b    | something | 1       |
| 3       | title c    | something | 0       |

注意:为了获得更好的性能,您需要在posts_flags(post_id).

于 2019-09-09T19:22:21.863 回答
2

计算 GROUP BY 查询中的标志数,并检查标志数是否大于零:

select
  p.post_id,
  p.post_title,
  p.post_body,
  count(f.post_id) > 0 as flagged
from posts p
left join posts_flags f on f.post_id = p.post_id
group by p.post_id, p.post_title, p.post_body

你也可以使用

min(f.post_id) is not null as flagged

这可能看起来令人困惑,但它避免了阅读帖子的所有标志。

于 2019-09-09T19:26:15.040 回答