WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   Sql fråga (https://www.wn.se/forum/showthread.php?t=23346)

Robert 2007-09-03 18:14

Antag att jag har 3 tabeller; 2 st med diverse data samt 1 kopplingstabell mellan dessa.

Undrar om någon vänlig själ kan visa hur man söker fram data som visar vart det _saknas_ kopplingar. Här antar jag alltså att ett normalfall är att alla rader i tabell 1 är kopplade mot alla rader i tabell 2 (via tabell 3). Hur söker man ut något som "saknas" till skillnad från det vardagliga där man faktiskt selectar fram saker som existerar? :unsure:

eg0master 2007-09-03 18:51

outer join och kolla så att "injoinad" kolumn är null.

Robert 2007-09-03 20:34

Men det är ju kopplingstabellen som pekar ut rader i tabell 1 och tabell 2. Vad ska jag joina på för att hitta saknade kopplingar?

allstars 2007-09-03 21:03

Använd WHERE NOT IN på något sätt, borde fungera.

Kod:

SELECT ID FROM tabell2 WHERE NOT IN (SELECT ... FROM Tabell2)

martine 2007-09-03 23:06

Du kan ju alltid göra en LEFT JOIN:
Kod:

SELECT tabell1.*,tab1_id FROM tabell1 LEFT JOIN koppling ON koppling.tab1_id=tabell1.id WHERE tab1_id IS NULL
för att få alla rader i tabell1 som inte är kopplade.

(enligt den här principen borde du få ut det du är ute efter, du kan ju fila på det för att få ut allt i en query eller hur du nu vill ha det)

Robert 2007-09-04 11:04

Om vi antar att tabell 1 har 10 rader samt tabell 2 har 1000 rader så kan det alltså finnas 10000 rader i kopplingstabellen (alla till alla).
Ponera att jag tar bort 1 rad ur kopplingstabellen, så kanske problemet klarnar varför jag har svårt att se vad som saknas... eller? :/

martine 2007-09-04 12:41

Citat:

Originally posted by Robert@Sep 4 2007, 11:04
Om vi antar att tabell 1 har 10 rader samt tabell 2 har 1000 rader så kan det alltså finnas 10000 rader i kopplingstabellen (alla till alla).
Ponera att jag tar bort 1 rad ur kopplingstabellen, så kanske problemet klarnar varför jag har svårt att se vad som saknas... eller? :/

Med räkneexempel kommer du oftast inte långt, även om antalet stämmer kan du ha referenser till rader som saknas i ena, andra eller båda tabellerna eller dubletter (om du inte har index som garanterar unikitet, vilket du förvisso borde ha) i "kopplingstabellen".

Vad är det du letar efter? Misstänker du att id:n är refererade till i kopplingstabellen som saknas i tabell 1 eller 2, eller letar du efter rader som finns i tabellerna men inte är "kopplade"? Försök formulera vad du är ute efter lite noggrannare!

Det har ju kommit flera förslag på hur du kan gå till väga rent sgl-mässigt här (mer detaljerat kan det inte bli om du inte lägger upp tabellerna i sin helhet och talar om exakt vad det är du söker efter…). Om du tar bort en rad så får du ju ett null-värde som du kan söka efter när du gör en outerjoin, vad är det mer du behöver?

Robert 2007-09-04 16:11

Räkneexemplet var till för att visa att man med en join får "träff" just för att det existerar en kopplingar öht, dock så vet man ju inte att samtliga kopplingar finns.

Riktigt exempel: Ett översättningsscenario där du har tabeller som följer:

1) Languages (språk)
2) Phrases (engelska fraser)
3) Translation (en koppling mellan ovanstående (pekar mot id i båda tabellerna). Innehåller också det översatta ordet på det aktuella språket)
Mer data än så behövs inte för att förstå problemet. :)

Jag måste ha en sql för att leta efter ord som saknar översättning, oavsett vilken Phrase eller Language det gäller. Join-exemplen ni gav ger ju "träff" bara en phrase har minst en översättning på ett språk, och det är inte riktigt vad jag är ute efter.

b.n: Det finns inga dubletter i kopplingstabellen.

Robert 2007-09-12 23:07

Ingen som vill försöka? :/

Jake.Nu 2007-09-13 04:26

SELECT id FROM koppling WHERE id NOT IN(SELECT id FROM tabell_a) AND id NOT IN(SELECT id FROM tabell_b)

SimonP 2007-09-13 10:08

Jag tror du måste göra så här:

Pseudo-kod:

Kod:

SELECT lang_id FROM Languges

Loop
{
 $langid=hämta_första row['lang_id'];
 SELECT phrase_id FROM phrases WHERE phrase_id NOT IN (SELECT lang_id,phrase_id FROM Translation WHERE lang_id=$langid)
 echo "Dessa översättningar saknas i språket $langid"
 skriv ut resultatet från SELECT satsen
}


fors 2007-09-14 09:19

Detta borde fungera:

Kod:

SELECT l.name, p.phrase
FROM languages AS l
JOIN phrases AS p
LEFT JOIN translation AS t ON t.lang_id = l.id AND t.phrase_id = p.id
WHERE t.translation IS NULL


Robert 2007-09-14 19:35

Tack, jag ska kolla upp detta när jag är tillbaka på jobbet på måndag.

Robert 2007-09-18 01:14

Jake.Nu: I ditt exempel försöker du plocka fram kopplingar som inte är kopplade om man säger så. Det är lite fel tyvär, det ska vara kopplingar som inte existerar. Din sql ger alltså inga träffar ö.h.t

SimonP: Jag vill helst inte loopa i serverkod för det blir en sjuh***lvetes massa slagningar mot databasen.

fors: Du verkar nästan vara där, men jag förstår inte din "JOIN phrases AS p"... man ska väl joina den på något enligt t-sql dialekten iaf. ?

SimonP 2007-09-18 01:45

Citat:

Originally posted by Robert@Sep 18 2007, 00:14
SimonP: Jag vill helst inte loopa i serverkod för det blir en sjuh***lvetes massa slagningar mot databasen.

Fast det blir bara en loop per språk, har du så många olika språk?
Anledningen till att jag loopade var att jag inte kom på nån bra Query, men om nån kommer på en Query som fungerar så är det iofs bättre att köra på en sån.

fors 2007-09-18 08:43

Citat:

Originally posted by Robert@Sep 18 2007, 00:14
Jake.Nu: I ditt exempel försöker du plocka fram kopplingar som inte är kopplade om man säger så. Det är lite fel tyvär, det ska vara kopplingar som inte existerar. Din sql ger alltså inga träffar ö.h.t

SimonP: Jag vill helst inte loopa i serverkod för det blir en sjuh***lvetes massa slagningar mot databasen.

fors: Du verkar nästan vara där, men jag förstår inte din "JOIN phrases AS p"... man ska väl joina den på något enligt t-sql dialekten iaf. ?

Utan att sätta några villkor på tabellkopplingen så kommer man få en lista innehållande kombinationer av alla raderna i de två tabellerna. Dvs, om det finns 10 språk och 10 000 fraser så får du en lista med alla kombinationer av dessa (10 * 10 000 = 100 000 olika kombinationer). Därefter använder man translation-tabellen för att ta fram de raderna som är intressanta.

Har du testat SQL-satsen? Den fungerar åtminstone när jag testar den i MySQL. Sedan hur man gör i T-SQL, det vet jag inte. Men jag skulle kunna gissa på att den här frågan inte är MySQL-specifik.

Robert 2007-09-19 09:03

SimonP: Jag har 20 språk... :(

fors: Jag har givetvis testat (med mina tabell-/kolumnnamn då) och får ett syntax fel, "Incorrect syntax near the keyword 'join'.". Jag har försökt att modifiera syntaxen utan att få det att fungera på det sätt jag vill. Jag ser ju att din princip är korrekt, så inga problem där, bara syntaxfelet som måste fixas..

[edit] Ska tillägga att om man tar bort JOIN och bara söker fram phrases i FROM så fungerar det, men då crashar LEFT JOIN satsen med felet "The multi-part identifier "l.Id" could not be bound.". Jag gjorde enligt följande istället:

Kod:

SELECT l.name, p.phrase
FROM languages AS l,
phrases AS p
LEFT JOIN translation AS t ON t.lang_id = l.id AND t.phrase_id = p.id
WHERE t.translation IS NULL



Alla tider är GMT +2. Klockan är nu 15:13.

Programvara från: vBulletin® Version 3.8.2
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Svensk översättning av: Anders Pettersson