我有以下表格:
news
idNews | title
1 | Title 1
2 | Title 2
3 | Title 3
4 | Title 4
tags
idTag | name
1 | Name_tag1
2 | Name_tag2
3 | Name_tag3
4 | Name_tag4
MappingTable:
tag_news
idTag | idNews
1 | 1
2 | 1
1 | 2
2 | 2
2 | 3
3 | 3
4 | 3
4 | 4
我想通过赠送一个idNews来获取几乎有一个共同标签的相关新闻的标题。我可以用三个SELECT来做到这一点:
SELECT title FROM news WHERE idNews IN
(SELECT DISTINCT idNews FROM tag_news
WHERE idTag IN
(SELECT idTag FROM tag_news WHERE idNews='$idNews'))
其中$ idNews标识我通过参数提供的ID。
这很有效,但我想如果还有其他方法可以改进查询。
提前致谢, 伊克尔
答案 0 :(得分:6)
在SQL中编程时,您确实需要了解联接。连接是SQL的基础,因为while循环是大多数其他编程语言的基础。
SELECT DISTINCT n.title FROM news n
INNER JOIN tag_news t1 ON t1.idNews = n.idNews
INNER JOIN tag_news t2 ON t1.idTag = t2.idTag
WHERE t2.idNews = $idNews;
从A Visual Explanation of SQL Joins
开始来自@Beth的评论:
我并不是要与你发生冲突,但我很确定我的查询是正确的,并且它不需要三个连接。以下是它的工作原理:
t2
是tag_news
中t2.idNews=$idNews
的行集。例如,如果$ idNews = 1,则会生成以下行:
idTag | idNews
1 | 1
2 | 1
从那里,我们希望tag_news中的所有其他行匹配任何相同的标记。所以t1.idTag=t2.idTag
。这个产生给我们t1.idTag IN (1,2)
:
idTag | idNews
1 | 1
2 | 1
1 | 2
2 | 2
2 | 3
从那里,返回news
中与t1.idNews
的任何值匹配的所有行。换句话说,news.idNews IN (1,2,3)
。
idNews | title
1 | Title 1
2 | Title 2
3 | Title 3
答案 1 :(得分:2)
尝试:
SELECT distinct title
FROM
tag_news t1 inner join
tag_news t2 on
t1.idnews = t2.idnews inner join
tag_news t3 on
t2.idtag = t3.idtag inner join
news n on
n.idnews = t3.idnews
WHERE t1.idNews='$idNews'
抱歉,第一次和第二次错过了它:
CREATE TABLE [dbo].news(
idnews [int] NOT NULL,
title [varchar](50) NULL
) ON [PRIMARY]
insert into news(idnews, title) values(1,'title 1')
insert into news(idnews, title) values(2,'title 2')
insert into news(idnews, title) values(3,'title 3')
insert into news(idnews, title) values(4,'title 4')
CREATE TABLE [dbo].tag_news(
idtag [int] NOT NULL,
idnews [int] NOT NULL,
) ON [PRIMARY]
insert into tag_news(idtag, idnews) values(1,1)
insert into tag_news(idtag, idnews) values(2,1)
insert into tag_news(idtag, idnews) values(1,2)
insert into tag_news(idtag, idnews) values(2,2)
insert into tag_news(idtag, idnews) values(2,3)
insert into tag_news(idtag, idnews) values(3,3)
insert into tag_news(idtag, idnews) values(4,3)
insert into tag_news(idtag, idnews) values(4,4)
select * from news;
select * from tag_news;
SELECT title FROM news WHERE idNews IN
(SELECT DISTINCT idNews FROM tag_news
WHERE idTag IN
(SELECT idTag FROM tag_news WHERE idNews=1));
SELECT distinct title
FROM
tag_news t1 inner join
tag_news t2 on
t1.idnews = t2.idnews inner join
tag_news t3 on
t2.idtag = t3.idtag inner join
news n on
n.idnews = t3.idnews
WHERE t1.idNews=1;