2013-10-14 16 views
5

Sto riscontrando alcuni problemi con una query che genera duplicati quando eseguo un join interno tra alcune tabelle.SQL table multiple join throwing dupes

In sostanza, sto unendo alcuni tag e canali (penso al genere) in base al videoId in modo che un particolare file video possa avere più tag e essere parte di più canali.

Purtroppo, più corrispondenze appaiono :(La mia sensazione è che la query è la corrispondenza contro il videoId per ogni join e sputando il raddoppio (come vedrete nel violino legato, ma considerando che il mio totale di SQL L'esperienza di partecipazione è di circa 3 ore fa Sono riuscito a confondermi con OK finora, ma ora potrei fare un po 'di consigli da esperti su dove andare.

Di seguito è riportato lo schema e la query che ho stato alle prese con, e qui è un sqlfiddle collegamento,

schema:

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); 

Query:

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; 

Sto andando su questo nel modo giusto? C'è solo un errore fondamentale sul modo in cui ho strutturato la query che sta facendo questo? O è lo schema sbagliato per quello che sto cercando di realizzare.

Qualsiasi aiuto sarebbe molto apprezzato!

@ J Grazie per la risposta!

Risposta: la parola chiave DISTINCT, ho provato nell'istruzione SELECT, ma era incerto su suo utilizzo in modo da non apprezzare appieno dove potrebbe essere utilizzata, @J Lo così succintamente ha sottolineato, posso usarlo nel mio group_concat, dando così la query:

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; 
+0

Questo è giusto mysql? In questo caso non dovresti usare il tag sql-server. Ma grazie per aver preparato la tua domanda così bene. – Szymon

+1

Ciao amico, sono andato con i tag suggeriti, avrei dovuto leggerli un po 'più da vicino. – splintex

risposta

3

tua prima coppia si unisce (Video/VideoTags/Tag) produce un tavolo in questo modo:

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

| 1 | Dogs 
| 1 | orlyowl 

Quando si partecipa a VideoChannels, duplica il voci di cui sopra per ciascun canale

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

group_concat ha un attributo 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; 
+0

Volevo il gruppo TAGS e il gruppo CHANNELS nel set di risultati mostrato ** [QUI] (http://www.sqlfiddle.com/#!2/765385/1/0) ** ma senza il doppio ups che stanno accadendo. Credo di aver appena confuso nella mia testa come dovrebbero funzionare i join. Voglio recuperare tutti i ** TAG ** associati a un particolare file video, così come tutti i ** CANALI ** di cui fa parte. Il collegamento SQLFiddle ti darà praticamente quello che voglio che assomigli. Grazie per aver trovato il tempo di rispondere. – splintex

+0

@ J Grazie! Foresta per gli alberi, penso, ho provato DISTINCT ma nel posto sbagliato. Dovrebbe aver letto un po 'di più sul suo utilizzo. Mi ha ordinato in breve tempo, e ancora, molte grazie. – splintex