1

次のテーブルがあります。

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

マッピング テーブル:

tag_news
idTag | idNews
1     | 1
2     | 1
1     | 2
2     | 2
2     | 3
3     | 3
4     | 3
4     | 4

1 つの idNews を指定して、ほぼ 1 つのタグが共通する関連ニュースのタイトルを取得したいと考えています。私は3つの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 は、パラメーターで指定した ID です。

これはうまく機能しますが、クエリを改善する別の方法があるかどうかを考えました。

前もって感謝します、イケル

4

2 に答える 2

6

SQL でプログラミングするときは、結合を理解する必要があります。while ループが他のほとんどのプログラミング言語の基本であるように、結合は SQL の基本です。

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;

SQL結合の視覚的な説明から始めましょう


@Beth からの再コメント:

矛盾するつもりはありませんが、私のクエリは正しいと確信しており、3 つの結合は必要ありません。仕組みは次のとおりです。

  • t2tag_newswhereの行のセットです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
    
于 2012-11-21T18:19:41.737 に答える
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'

申し訳ありませんが、1回目と2回目は見逃しました:

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;
于 2012-11-21T18:22:40.353 に答える