Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql 多行连接_Mysql_Sql_Join - Fatal编程技术网

Mysql 多行连接

Mysql 多行连接,mysql,sql,join,Mysql,Sql,Join,我试图根据其他表中是否有多行从posts表加载行。以下表为例: 帖子 post_id post_title ------------------- 1 My Post 2 Another Post post_tag_id post_tag_name -------------------------- 1 My Tag 2 Another Tag postTag_id postTag_tag_id postTag

我试图根据其他表中是否有多行从posts表加载行。以下表为例:

帖子

post_id  post_title
-------------------
1        My Post
2        Another Post
post_tag_id  post_tag_name
--------------------------
1            My Tag
2            Another Tag
postTag_id  postTag_tag_id  postTag_post_id
------------------------------------------
1           1               1
2           2               1
post_标签

post_id  post_title
-------------------
1        My Post
2        Another Post
post_tag_id  post_tag_name
--------------------------
1            My Tag
2            Another Tag
postTag_id  postTag_tag_id  postTag_post_id
------------------------------------------
1           1               1
2           2               1
postTags

post_id  post_title
-------------------
1        My Post
2        Another Post
post_tag_id  post_tag_name
--------------------------
1            My Tag
2            Another Tag
postTag_id  postTag_tag_id  postTag_post_id
------------------------------------------
1           1               1
2           2               1
毫不奇怪,post和post_标记存储了post和标记,posttag连接了哪些post具有哪些标记

我通常会这样加入表:

SELECT * FROM (`posts`)
JOIN `postTags` ON (`postTag_post_id` = `post_id`)
JOIN `post_tags` ON (`post_tag_id` = `postTag_tag_id`)
然后我会有关于标签的信息,并且可以在稍后的查询中添加其他内容来搜索标签名称以查找搜索词等,然后在我有与搜索词匹配的帖子后进行分组

我试图做的只是从一篇既有标记1又有标记2的文章中进行选择,而我无法计算出它的SQL。我认为这需要在实际的连接中完成,而不是在上面的连接中使用WHERE子句,因为当我运行上面的连接时,显然会返回两行,所以我不能有类似这样的内容

WHERE post_tag_id = 1 AND post_tag_id = 2
因为每一行只有一个post_tag_id,我不能在一行中检查同一列的不同值

我试着做的是这样的:

SELECT * FROM (`posts`)
JOIN `postTags` ON (postTag_tag_id = 1 AND postTag_tag_id = 2)
JOIN `post_tags` ON (`post_tag_id` = `postTag_tag_id`)
postTag_post_id | cnt
              1 |   2
SELECT post_id, post_title
FROM posts JOIN postTags ON (postTag_post_id = post_id)
WHERE postTag_tag_id IN (1, 2)
GROUP BY post_id, post_title
HAVING COUNT(DISTINCT postTag_tag_id) = 2
但当我运行它时,它返回0个结果;我以前在连接中为类似的事情设置过类似的条件,我确信这很接近,但无法确定如果这不起作用该怎么办

我至少在正确的轨道上吗?希望我没有错过什么明显的东西


谢谢。

您正试图要求postTags行同时处理一件事和另一件事

SELECT p.*, t1.*, t2.* FROM posts p
INNER JOIN postTags pt1 ON pt1.postTag_post_id = p.id AND pt1.postTag_tag_id = 1
INNER JOIN postTags pt2 ON pt2.postTag_post_id = p.id AND pt2.postTag_tag_id = 2
INNER JOIN post_tags t1 ON t1.post_tag_id = pt1.postTag_tag_id
INNER JOIN post_tags t2 ON t2.post_tag_id = pt2.postTag_tag_id
您需要对post_标记和postTags执行两个连接,以便同时获得这两个标记。或者你可以说,文章可以在这两个标签之间有任何标签,标签的总量必须等于两个(假设一篇文章不能多次与同一个标签相关)

第一种方法:

SELECT *
FROM `posts` as p
WHERE p.`post_id` IN (SELECT pt.`postTag_post_id`
                      FROM `postTags` as pt
                      WHERE pt.`postTag_tag_id` = 1)
AND p.`post_id` IN (SELECT pt.`postTag_post_id`
                    FROM `postTags` as pt
                    WHERE pt.`postTag_tag_id` = 2);
SELECT *
FROM posts as p
WHERE p.post_id IN (SELECT pt.postTag_post_id
                    FROM (SELECT count(0) as c, pt.postTag_post_id
                          FROM postTags as pt
                          WHERE pt.postTag_tag_id IN (1, 2)
                          GROUP BY pt.postTag_post_id
                          HAVING c = 2) as pt);
第二种方法:

SELECT *
FROM `posts` as p
WHERE p.`post_id` IN (SELECT pt.`postTag_post_id`
                      FROM `postTags` as pt
                      WHERE pt.`postTag_tag_id` = 1)
AND p.`post_id` IN (SELECT pt.`postTag_post_id`
                    FROM `postTags` as pt
                    WHERE pt.`postTag_tag_id` = 2);
SELECT *
FROM posts as p
WHERE p.post_id IN (SELECT pt.postTag_post_id
                    FROM (SELECT count(0) as c, pt.postTag_post_id
                          FROM postTags as pt
                          WHERE pt.postTag_tag_id IN (1, 2)
                          GROUP BY pt.postTag_post_id
                          HAVING c = 2) as pt);
我还想补充一点,如果在第一种方法中使用或存在,那么就不会因为有多个标记而在同一个post行中有多行。通过这种方式,您可以稍后保存一个不同的文件,这将使您的查询速度变慢。
我在第二种方法中使用了IN,这是我使用的一条经验法则:如果不需要显示数据,则不需要在FROM部分进行连接。

您试图要求postTags行同时显示一件事和另一件事

您需要对post_标记和postTags执行两个连接,以便同时获得这两个标记。或者你可以说,文章可以在这两个标签之间有任何标签,标签的总量必须等于两个(假设一篇文章不能多次与同一个标签相关)

第一种方法:

SELECT *
FROM `posts` as p
WHERE p.`post_id` IN (SELECT pt.`postTag_post_id`
                      FROM `postTags` as pt
                      WHERE pt.`postTag_tag_id` = 1)
AND p.`post_id` IN (SELECT pt.`postTag_post_id`
                    FROM `postTags` as pt
                    WHERE pt.`postTag_tag_id` = 2);
SELECT *
FROM posts as p
WHERE p.post_id IN (SELECT pt.postTag_post_id
                    FROM (SELECT count(0) as c, pt.postTag_post_id
                          FROM postTags as pt
                          WHERE pt.postTag_tag_id IN (1, 2)
                          GROUP BY pt.postTag_post_id
                          HAVING c = 2) as pt);
第二种方法:

SELECT *
FROM `posts` as p
WHERE p.`post_id` IN (SELECT pt.`postTag_post_id`
                      FROM `postTags` as pt
                      WHERE pt.`postTag_tag_id` = 1)
AND p.`post_id` IN (SELECT pt.`postTag_post_id`
                    FROM `postTags` as pt
                    WHERE pt.`postTag_tag_id` = 2);
SELECT *
FROM posts as p
WHERE p.post_id IN (SELECT pt.postTag_post_id
                    FROM (SELECT count(0) as c, pt.postTag_post_id
                          FROM postTags as pt
                          WHERE pt.postTag_tag_id IN (1, 2)
                          GROUP BY pt.postTag_post_id
                          HAVING c = 2) as pt);
我还想补充一点,如果在第一种方法中使用或存在,那么就不会因为有多个标记而在同一个post行中有多行。通过这种方式,您可以稍后保存一个不同的文件,这将使您的查询速度变慢。
我在第二种方法中使用了IN,这是我使用的一条经验法则:如果不需要显示数据,则不需要在FROM部分进行连接。

如果不实际构建与您相同的数据库,这很难验证,但应该是可行的

首先,我要说的是,在支持分析查询的数据库(Oracle、MS SQL Server)中,这种类型的查询要容易得多,性能也要高得多。因此,在MySQL中,您必须使用旧的、蹩脚的、聚合的方式

我还想说的是,有一个表存储post_标记中的标记名称,然后将post标记映射到postTags中的post是令人困惑的。如果是我,我会将映射表的名称更改为post_tags_map或post_tags_to_post_map。因此,您将拥有具有post\U id的post\U标记、具有post\U标记\U id的post\U标记以及具有post\U标记\U映射\U id的post\U标记。并且这些id列在每个表中的名称都相同。同样的列在其他表中以不同的名称命名也是令人困惑的

不管怎样,让我们来解决你的问题。 首先,您需要一个结果集,该结果集是每行1个post id,并且仅包含标记为1和2的post

select postTag_post_id, count(1) cnt from (
  select postTag_post_id from postTags where postTag_tag_id in (1, 2)
) group by postTag_post_id;`
这将返回如下数据:

SELECT * FROM (`posts`)
JOIN `postTags` ON (postTag_tag_id = 1 AND postTag_tag_id = 2)
JOIN `post_tags` ON (`post_tag_id` = `postTag_tag_id`)
postTag_post_id | cnt
              1 |   2
SELECT post_id, post_title
FROM posts JOIN postTags ON (postTag_post_id = post_id)
WHERE postTag_tag_id IN (1, 2)
GROUP BY post_id, post_title
HAVING COUNT(DISTINCT postTag_tag_id) = 2
然后可以将该结果集连接回posts表

select * from posts p,
(
  select postTag_post_id, count(1) cnt from (
    select postTag_post_id from postTags where postTag_tag_id in (1, 2)
  ) group by postTag_post_id;
) t
where p.post_id = t.postTag_post_id
and t.cnt >= 2;
如果为了从post_tag_名称中获取postTag_tag_id,需要对post_tags表进行另一次联接,则最内部的查询将更改如下:

select postTag_post_id
from postTags a,
post_tags b
where a.postTag_tag_id = b.post_tag_id
and b.post_tag_name in ('tag 1', 'tag 2');

这应该可以解决问题。

如果不实际构建与您相同的数据库,这很难验证,但应该可以工作

首先,我要说的是,在支持分析查询的数据库(Oracle、MS SQL Server)中,这种类型的查询要容易得多,性能也要高得多。因此,在MySQL中,您必须使用旧的、蹩脚的、聚合的方式

我还想说的是,有一个表存储post_标记中的标记名称,然后将post标记映射到postTags中的post是令人困惑的。如果是我,我会将映射表的名称更改为post_tags_map或post_tags_to_post_map。因此,您将拥有具有post\U id的post\U标记、具有post\U标记\U id的post\U标记以及具有post\U标记\U映射\U id的post\U标记。并且这些id列在每个表中的名称都相同。同样的列在其他表中以不同的名称命名也是令人困惑的

不管怎样,让我们来解决你的问题。 首先,您需要一个结果集,该结果集是每行1个post id,并且仅包含标记为1和2的post

select postTag_post_id, count(1) cnt from (
  select postTag_post_id from postTags where postTag_tag_id in (1, 2)
) group by postTag_post_id;`
这将返回如下数据:

SELECT * FROM (`posts`)
JOIN `postTags` ON (postTag_tag_id = 1 AND postTag_tag_id = 2)
JOIN `post_tags` ON (`post_tag_id` = `postTag_tag_id`)
postTag_post_id | cnt
              1 |   2
SELECT post_id, post_title
FROM posts JOIN postTags ON (postTag_post_id = post_id)
WHERE postTag_tag_id IN (1, 2)
GROUP BY post_id, post_title
HAVING COUNT(DISTINCT postTag_tag_id) = 2
然后可以将该结果集连接回posts表

select * from posts p,
(
  select postTag_post_id, count(1) cnt from (
    select postTag_post_id from postTags where postTag_tag_id in (1, 2)
  ) group by postTag_post_id;
) t
where p.post_id = t.postTag_post_id
and t.cnt >= 2;
如果为了从post_tag_名称中获取postTag_tag_id,需要对post_tags表进行另一次联接,则最内部的查询将更改如下:

select postTag_post_id
from postTags a,
post_tags b
where a.postTag_tag_id = b.post_tag_id
and b.post_tag_name in ('tag 1', 'tag 2');

这应该就可以了。

假设您已经知道标记ID(
1
2
),您可以这样做:

SELECT * FROM (`posts`)
JOIN `postTags` ON (postTag_tag_id = 1 AND postTag_tag_id = 2)
JOIN `post_tags` ON (`post_tag_id` = `postTag_tag_id`)
postTag_post_id | cnt
              1 |   2
SELECT post_id, post_title
FROM posts JOIN postTags ON (postTag_post_id = post_id)
WHERE postTag_tag_id IN (1, 2)
GROUP BY post_id, post_title
HAVING COUNT(DISTINCT postTag_tag_id) = 2
注意:如果
postTags{postTag\u tag\u id,postTag\u post\u id}
上有备用键,则不需要使用DISTINCT

注意:如果没有标记ID(只有标记名),则需要另一个连接(指向
post\u tags
表)