SQL多表连接抛出骗子

Posted

技术标签:

【中文标题】SQL多表连接抛出骗子【英文标题】:SQL multiple table join throwing dupes 【发布时间】:2013-10-14 04:18:46 【问题描述】:

当我在一些表之间进行内部联接时,我遇到了一些问题,查询会引发欺骗。

基本上,我加入了一些标签和基于 videoId 的频道(想想流派),因此特定的视频文件可以有多个标签并成为多个频道的一部分。

不幸的是,出现了多个匹配项 :( 我的直觉是查询与每个连接的 videoId 匹配并吐出双倍(正如您将在链接的小提琴中看到的那样,但考虑到我的 SQL 连接总数经验是从大约 3 小时前开始的,到目前为止,我已经勉强过得很好,但现在可以通过一些专家建议来了解如何从这里开始。

以下是我一直在努力解决的架构和查询,这是一个sqlfiddle 链接,

架构:

create table videos 
(
   videoId int(1) AUTO_INCREMENT,
   videoUUID char(40),
   contentFolder varchar(50), 
   title varchar(50), 
   caption varchar(50),
   duration varchar(15),
   date TIMESTAMP,
   url varchar(55),
   text varchar(250), 
   PRIMARY KEY (videoId)
);

create table tags 
( 
   tagId int(1) AUTO_INCREMENT,
   tagName varchar(15),
   PRIMARY KEY (tagId)
);

create table channels
(
   channelId int(1) AUTO_INCREMENT,
   channelName varchar(15),
   PRIMARY KEY (channelId)
);

create table videoTags 
(
   videoTagId int(1) AUTO_INCREMENT,
   videoId int(1),
   tagId int(1),
   PRIMARY KEY (videoTagId)
);

create table videoChannels 
(
    videoChannelId int(1) AUTO_INCREMENT,
    videoId int (1),
    channelId int (1),
    PRIMARY KEY (videoChannelId)
 );

//
create trigger tuuid before insert on videos
for each row begin
set new.videoUUID = uuid();
end//

insert into videos 
  (contentFolder, title,caption,duration,url,text)
values ("someDir/","A Movie Title", "Headline for Movie",
    "00:05:11",
    "http://someserver.ip/somedir/test.mp4",
    "Some text as part of the video file description here");

insert into tags (tagName) values
('Flowers'),('Dogs'),('Cats'),('YaMum'),('orlyowl');

insert into channels (channelName) values
('General'), ('NotSoGeneral'), ('Specific'), ('Broad'), ('Narrow'),
('Obsolete'); 

insert into videoTags (videoId,tagId) values
(1,2),(1,5);

insert into videoChannels (videoId,channelId) values
(1,1),(1,4),(1,6);

查询:

select distinct v.*,group_concat(t.tagName)Tags,
group_concat(c.channelName)Channels
from videos as v 

inner join videoTags as vt on v.videoId = vt.videoid

inner join tags as t on t.tagId = vt.tagId

inner join videoChannels as vc on v.videoId = vc.videoId

inner join channels as c on c.channelId = vc.channelId

group by v.videoId;

我这样做的方式是否正确?我构建正在执行此操作的查询的方式是否存在根本错误?或者我想要完成的架构是错误的。

任何帮助将不胜感激!

@J Lo 感谢您的回答!

答案: DISTINCT 关键字,我在 select 语句中尝试过,但不确定它的用法,所以没有完全理解它可以在哪里使用,@J Lo 如此简洁地指出,我可以在我的 group_concat 中使用它,从而给出查询:

select v.*,group_concat(distinct t.tagName)Tags,
group_concat(distinct c.channelName)Channels
from videos as v 

inner join videoTags as vt on v.videoId = vt.videoid

inner join tags as t on t.tagId = vt.tagId

inner join videoChannels as vc on v.videoId = vc.videoId

inner join channels as c on c.channelId = vc.channelId

group by v.videoId;

【问题讨论】:

这是mysql吧?在这种情况下,您不应该使用 sql-server 标记。但是感谢您准备好您的问题。 干杯伙伴,我只是使用建议的标签,应该更仔细地阅读它们。 【参考方案1】:

您的第一对连接 (Video/VideoTags/Tags) 会产生如下表格:

VideoID = 1 will bring in TagID = 2,5 (Dogs, orlyowl) so you have this

| 1 | Dogs
| 1 | orlyowl

当您加入 VideoChannels 时,它会为每个频道复制上述条目

| 1 | Dogs    | 1
| 1 | orlyowl | 1
| 1 | Dogs    | 4
| 1 | orlyowl | 4
| 1 | Dogs    | 6
| 1 | orlyowl | 6

group_concat 有一个 DISTINCT 属性

select v.*
  , group_concat(distinct t.tagName) Tags
  , group_concat(distinct c.channelName) Channels
from videos as v 
inner join videoTags as vt on v.videoId = vt.videoid
inner join tags as t on t.tagId = vt.tagId
inner join videoChannels as vc on v.videoId = vc.videoId
inner join channels as c on c.channelId = vc.channelId
group by v.videoId;

【讨论】:

我想要显示 HERE 的结果集中的 TAGS 组和 CHANNELS 组,但没有发生双倍提升。我想我只是对连接应该如何工作感到困惑。我想检索与特定视频文件关联的所有 TAGS,以及它所属的所有 CHANNELS。 SQLFiddle 链接将为您提供我想要的外观。感谢您抽出宝贵时间回复。 @J Lo 谢谢!我认为树木的森林,我尝试了 DISTINCT 但在错误的地方。应该阅读更多有关其用法的信息。很快就把我整理出来了,再次感谢。

以上是关于SQL多表连接抛出骗子的主要内容,如果未能解决你的问题,请参考以下文章

SQL多表连接查询(详细实例)

sql多表连接查询问题

SQL多表连接

SQL多表连接查询(详细实例)

SQL多表查询

SQL语句多表连接查询语法