webForumDet fria alternativet

Endast unikt id från JOIN

Databaser & SQL

13 svar · 754 visningar · startad av dreas

Medlem sedan jan. 2004140 inlägg
Frågan#1

Hej,
Har en SQL sats som ska ta ut ett gäng "quicks" från en tabell som heter match_has_quicks. Varje unik match (matches_id) kan alltså ha flera quicks. Allting fungerar toppen med satsen än så länge. Det jag dock inte får till är att få den att sortera ut så den bara visar den första matchens quicks i queryn, och inte alla matcher som uppfyller datum regeln.

SELECT quicks.id AS quick_id, quicks.title AS quick_title, matches.id AS match_id
FROM match_has_quicks mQ
INNER JOIN quicks ON quicks.id = mQ.quicks_id
INNER JOIN matches ON matches.id = mQ.matches_id
WHERE matches.gameset_id=:gameset_id AND matches.played_at>=".date("Y-m-d")."
ORDER BY matches.played_at ASC, mQ.matches_id
Medlem sedan dec. 20025 483 inlägg
#2

Vilken är "den första matchen"?

Medlem sedan jan. 2004140 inlägg
#3

Den första matchen blir ju den match i ledet av som uppfyller att datumet (i kolumnen played_at) fortfarande inte är uppfyllt (dvs, den visar ingen spelad match) sorterat på played_at (ASC) och matches_id i tabellen match_has_quicks (om det mot förmodan skulle finnas två matcher under samma dag, så får man utgå ifrån att minsta match id är den första och alltså den jag vill visa)

ORDER BY matches.played_at ASC, mQ.matches_id

Jag vill alltså få ut ENBART en match, och det är den första matchen efter sorteringen i SQL-satsen.

Detta är arrayen jag får ut med enbart två matcher liggandes i match_has_quicks (infaller på samma dag), om det kan vara till hjälp:

Array ( [0] => Array ( [quick_id] => 1 [0] => 1 [quick_title] => Vinnare av f�rsta halvlek [1] => Vinnare av f�rsta halvlek [match_id] => 10 [2] => 10 ) 
[1] => Array ( [quick_id] => 2 [0] => 2 [quick_title] => F�rsta m�let [1] => F�rsta m�let [match_id] => 10 [2] => 10 ) 
[2] => Array ( [quick_id] => 3 [0] => 3 [quick_title] => Första frisparken [1] => Första frisparken [match_id] => 10 [2] => 10 ) 
[3] => Array ( [quick_id] => 3 [0] => 3 [quick_title] => Första frisparken [1] => Första frisparken [match_id] => 11 [2] => 11 ) )

Notera sista raden, [match_id] => 11 , medan resten är [match_id] => 10
I detta fall vill jag alltså sortera bort så jag bara har [match_id] => 10

Medlem sedan dec. 20025 483 inlägg
#4
SELECT 
	quicks.id AS quick_id, 
	quicks.title AS quick_title, 
	m.id AS match_id
FROM 
	match_has_quicks mQ INNER JOIN quicks 
	ON 
	quicks.id = mQ.quicks_id
		INNER JOIN matches m
		ON 
		m.id = mQ.matches_id
WHERE 
	m.gameset_id=:gameset_id AND 
	m.played_at >= ".date("Y-m-d")." AND
	m.id = ( select min(q.id) from matches q
		inner join match_has_quicks z on q.id = z.matches_id
		inner join quicks x on x.id = z.quicks_id
		where q.played_at = m.played_at and q.gameset_id = m.gameset_id )
ORDER BY 
	m.played_at ASC, 
	mQ.matches_id
Medlem sedan jan. 2004140 inlägg
#5

Stiligt! Tusen tack, blir en guldstjärna i kanten Peter! (y)

Red: Om någon har nytta av att använda denna kod som Peter S postat kan jag tillägga att SQL satsen körs via PDO (php), dvs gameset_id=:gameset_id pekar på:

$stmt->bindParam(":gameset_id", $gameset_id);
Medlem sedan jan. 2004140 inlägg
#6

hmm, kom fram till att jag behöver komplettera SQL satsens villkor med en rad som kontrollerar ifall matchens speltid har uppfyllts eller inte. Ungefär:

WHERE 
			m.gameset_id=:gameset_id AND 
			m.played_at >= ".date("Y-m-d")." AND  
			m.playtime <  '".$the_time["hours"].":".$the_time["minutes"]."' AND
			m.id = ( select min(q.id) from matches q............

Problemet är ju att villkoret m.playtime bara ska gälla OM dagens datum är satt till lika med. Annars kommer ju satsen inte gälla för alla dagar om m.playtime är större än tiden.

Känns kanske som om jag får ta ut detta och kontrollera i PHP istället, eller?

Medlem sedan jan. 2004140 inlägg
#7

Märkligt. Nu verkar det vara samma problem igen med satsen, den plockar ut fler än en match igen. Jag testade iofs koden tidigare idag, på matcher som hade datum som var satt till igår. Hur som helst, verkar det trots allt inte fungera. Detta är koden (ska vara samma som Peter S ovan, men bifogas utifall att)

SELECT 
	quicks.id AS quick_id, 
	quicks.title AS quick_title, 
	m.id AS match_id
FROM 
	match_has_quicks mQ INNER JOIN quicks 
	ON 
	quicks.id = mQ.quicks_id
		INNER JOIN matches m
		ON 
		m.id = mQ.matches_id 
WHERE 
	m.gameset_id=:gameset_id AND 
	m.played_at >= ".date("Y-m-d")." AND
	m.id = ( select min(q.id) from matches q
		inner join match_has_quicks z on q.id = z.matches_id
		inner join quicks x on x.id = z.quicks_id
		where q.played_at = m.played_at and q.gameset_id = m.gameset_id )
ORDER BY 
	m.played_at ASC, 
	mQ.matches_id

Och jag får följande array resultat:

Array ( 
[0] => Array ( [quick_id] => 1 [0] => 1 [quick_title] => Vinnare av f&#65533;rsta halvlek [1] => Vinnare av f&#65533;rsta halvlek [match_id] => 10 [2] => 10 ) 
[1] => Array ( [quick_id] => 2 [0] => 2 [quick_title] => F&#65533;rsta m&#65533;let [1] => F&#65533;rsta m&#65533;let [match_id] => 10 [2] => 10 ) 
[2] => Array ( [quick_id] => 3 [0] => 3 [quick_title] => Första frisparken [1] => Första frisparken [match_id] => 10 [2] => 10 ) 
[3] => Array ( [quick_id] => 1 [0] => 1 [quick_title] => Vinnare av f&#65533;rsta halvlek [1] => Vinnare av f&#65533;rsta halvlek [match_id] => 12 [2] => 12 ) 
[4] => Array ( [quick_id] => 3 [0] => 3 [quick_title] => Första frisparken [1] => Första frisparken [match_id] => 12 [2] => 12 ) )

match_has_quicks innehåller nu 5 poster som uppfylls av datum kravet, där
match_id 12 har 2 rader och
match_id 13 har 3.

Varför kommer match_id 10 in överhuvudtaget? Speldatum played_at är 2008-03-27 för match_id 10. Dock har match_id 10 minsta id:na i match_has_quicks.

Något jag missat? Eller skrivit fel utifrån Peter S tidigare kod?

Herrejisses, blir helt snurrig :)

Medlem sedan dec. 20025 483 inlägg
#8

Vad är primärnyckel i matches?

Medlem sedan jan. 2004140 inlägg
#9

Primärnyckel i matches är id , så det borde väl stämma? Alla tabeller har för övrigt id som primärnyckel. Något förslag? Märkligt beteende dock, att det tycktes fungera innan. Vet inte riktigt hur jag ska felsöka det. Kanske ska rensa ut alla matcher, och prova att lägga in nya och bevaka hur sql satsen hanterar dessa

Medlem sedan dec. 20025 483 inlägg
#10

Då testar vi så här i stället :)

SELECT 
	q.id AS quick_id, 
	q.title AS quick_title, 
	m.id AS match_id
FROM 
	match_has_quicks mQ INNER JOIN quicks q
	ON 
	q.id = mQ.quicks_id
		INNER JOIN matches m
		ON 
		m.id = mQ.matches_id 
WHERE 
	m.gameset_id=:gameset_id AND 
	m.played_at >= ".date("Y-m-d")." AND
	q.id = ( select min(z.id) from matches x
		inner join match_has_quicks y on x.id = y.matches_id
		inner join quicks z on z.id = y.quicks_id
		where m.played_at = x.played_at and m.gameset_id = x.gameset_id )
ORDER BY 
	m.played_at ASC, 
	mQ.matches_id
Medlem sedan jan. 2004140 inlägg
#11

Först och främst - stort tack för att du tar dig tid Peter S, uppskattar det riktigt mycket. Jag får tyvärr inte önskat resultat med ovanstående SQL, följande är array resultatet:

Array ( 
[0] => Array ( [quick_id] => 1 [0] => 1 [quick_title] => Vinnare av f&#65533;rsta halvlek [1] => Vinnare av f&#65533;rsta halvlek [match_id] => 10 [2] => 10 ) 
[1] => Array ( [quick_id] => 1 [0] => 1 [quick_title] => Vinnare av f&#65533;rsta halvlek [1] => Vinnare av f&#65533;rsta halvlek [match_id] => 12 [2] => 12 ) 
[2] => Array ( [quick_id] => 1 [0] => 1 [quick_title] => Vinnare av f&#65533;rsta halvlek [1] => Vinnare av f&#65533;rsta halvlek [match_id] => 13 [2] => 13 ) )

Nu har vi alltså de tre olika matcherna som match_has_quicks innehåller, vilket alltså inte är det jag är ute efter. Vet inte ifall det är något missförstånd, men det vi alltså efter strävar är att lista enbart t.ex. match_id = 12's alla quicks.

Medlem sedan dec. 20025 483 inlägg
#12

Hm, så här borde det vara:

SELECT 
	quicks.id AS quick_id, 
	quicks.title AS quick_title, 
	m.id AS match_id
FROM 
	match_has_quicks mQ INNER JOIN quicks 
	ON 
	quicks.id = mQ.quicks_id
		INNER JOIN matches m
		ON 
		m.id = mQ.matches_id
WHERE 
	m.gameset_id=:gameset_id AND 
	m.played_at >= ".date("Y-m-d")." AND
	m.id = ( select min(q.id) from matches q
		inner join match_has_quicks z on q.id = z.matches_id
		inner join quicks x on x.id = z.quicks_id
		where q.played_at >= ".date("Y-m-d")." and q.gameset_id = m.gameset_id )
ORDER BY 
	m.played_at ASC, 
	mQ.matches_id
Medlem sedan jan. 2004140 inlägg
#13

Får mycket bättre resultat nu! Tusen tack Peter! Du rodde det i hamn, och det är jag ytterst tacksam över!!!
En liten notis till de som ramlar in i den här tråden är att i PDO (PHP) måste man lägga date("Y-m-d") som en variabel i en bindParam.
Exempelvis:

$the_date = date("Y-m-d");
... SQL SATSEN OVAN DÄR date.. byts ut mot :the_date...
$stmt->bindParam(":the_date", $the_date);

Toppen Peter! TACK!

Medlem sedan dec. 20025 483 inlägg
#14

Härligt! :bire

291 ms totalt · 4 externa anrop · v20260731065814-full.a51de22e
132 ms — deklarationer (db)
0 ms — hämta statistik (cache)
157 ms — hämta tråd, inlägg och bilagor (db)
132 ms — ändringar (db)