WN

WN (https://www.wn.se/forum/index.php)
-   Serversidans teknologier (https://www.wn.se/forum/forumdisplay.php?f=4)
-   -   SQL hämta rader med vissa ord i (https://www.wn.se/forum/showthread.php?t=1058305)

Anaxa 2013-06-23 18:17

Citat:

Ursprungligen postat av jonny (Inlägg 20472479)
TESTA:
PHP-kod:

SELECT 
FROM movies 
JOIN movie_genres ON movie_genres
.movie_id movies.id 
WHERE movie_genres
.genre_id IN (1,2)
LIMIT 030


Den ger mig alla rader vad jag än stoppar in i IN()
PHP-kod:

SELECT 
FROM movies 
JOIN movie_genres ON movie_genres
.movie_id movies.id 
WHERE movie_genres
.genre_id IN (1,2,3,4


Conny Westh 2013-06-23 22:37

Citat:

Ursprungligen postat av Anaxa (Inlägg 20472478)
Okej conny, så om alla filmer enligt min tabell har likadant årtal i sitt 'year' fält så strider det emot tredje formens normalisering?

Jag funderade också hur på jag ska hämta alla filmer som har genrerna komedi och skräck.

Jag provade:
PHP-kod:

string(149"SELECT * FROM movies JOIN movie_genres ON movie_genres.movie_id = movies.id WHERE movie_genres.genre_id = 2 AND movie_genres.genre_id = 1 LIMIT 0, 30" 

vilket inte jag mig någonting eftersom samma värde kan inte vara 2 olika saker samtidigt. Men detta är det bästa jag kan komma på.

Kan du lägga upp DDL-scriptet och ett script med INSERT av data i alla tabellerna så underlättar det om du vill ha hjälp, så slipper jag sitta och knappa in detta manuellt....

Anaxa 2013-06-23 23:44

http://www.anaxa.se/sql.sql (kolumnen 'genres' i 'movies' skall tas bort. Han inte göra det innan jag exporterade)

Jag löste det jag vill ha hjälp med och det var att hämta ALLA filmer vars genrer kan vara både Action och Skräck. Alltså inte filmer som bara ha action och bara har skräck utan som har båda två.
Detta funkar bra med denna query:
PHP-kod:

SELECT m.* FROM movies m JOIN movie_genres mg ON mg.movie_id m.id AND mg.genre_id IN (111GROUP BY m.id HAVING COUNT(DISTINCT mg.genre_id) = 2 ORDER BY m.date ASC 

Här representerar 1 och 11 genrens ID

Men nu vill jag också hämta ALLA genrer en film har och lägg till det på ett eget fält: Action,Skräck,Komedi (det behöver inte vara avgränsat med komma). Bara så att jag kan få ut datan så att jag kan bearbeta den med PHP. Jag provade med detta:
PHP-kod:

SELECT m.*, GROUP_CONCAT(genres.name) AS genre_field FROM movies m JOIN movie_genres mg ON mg.movie_id m.id AND mg.genre_id IN (1,11JOIN genres ON mg.genre_id genres.id GROUP BY m.id HAVING COUNT(DISTINCT mg.genre_id) = 2 ORDER BY m.date ASC LIMIT 030 

Men ovanstående ger mig bara en rad med ett fält som heter genre_field med värdet 'Action,Skräck'. Värdet ska egentligen bli 'Action,Skräck,Fantasy'(alla genrer).

Filmen i fråga är Hansel och Gretel som ligger i movies-tabellen.

yakuzaemme 2013-06-24 00:05

Citat:

Ursprungligen postat av Anaxa (Inlägg 20472504)
Jag löste det jag vill ha hjälp med

"Jag" :rolleyes:

Conny Westh 2013-06-24 00:49

Citat:

Ursprungligen postat av Anaxa (Inlägg 20472504)
Men nu vill jag också hämta ALLA genrer en film har och lägg till det på ett eget fält: Action,Skräck,Komedi (det behöver inte vara avgränsat med komma). Bara så att jag kan få ut datan så att jag kan bearbeta den med PHP. Jag provade med detta:

.
.
.
Citat:

Ursprungligen postat av Anaxa (Inlägg 20472504)
Men ovanstående ger mig bara en rad med ett fält som heter genre_field med värdet 'Action,Skräck'. Värdet ska egentligen bli 'Action,Skräck,Fantasy'(alla genrer).

Filmen i fråga är Hansel och Gretel som ligger i movies-tabellen.

Blir bättre om du använder CODE och /CODE -taggarna i stället för PHP /PHP....

Är det så här du menar?

Kod:

use anaxa;

SELECT m.*, GROUP_CONCAT(genres.name) AS genre_field
FROM movies m
JOIN movie_genres mg ON mg.movie_id = m.id AND mg.genre_id IN (select id from genres)
JOIN genres ON mg.genre_id = genres.id
GROUP BY m.id
HAVING COUNT(DISTINCT mg.genre_id) = 2
ORDER BY m.date ASC LIMIT 0, 30;


Anaxa 2013-06-24 01:36

Inte riktigt.

Säg att en film har 5 olika genrer, Äventyr, Action, Komedi, Skräck och Sport. Vi kan även anta att det finns flera filmer som har liknande genrer.

Nu vill jag filtrera filmerna för att få fram alla de filmer som har både Action och Skräck som genrer. Detta löser jag igenom att köra:
Kod:

SELECT m.* FROM movies m JOIN movie_genres mg ON mg.movie_id = m.id AND mg.genre_id IN (1, 11) GROUP BY m.id HAVING COUNT(DISTINCT mg.genre_id) = 2 ORDER BY m.date ASC 
// Där 1, 11 representerar genrernas ID.

Här hämtar jag data enbart ifrån 'movies'. So far so good.
Men nu kommer vi till de knepiga och själva problemet.
Jag vill samtidigt hämta alla genrer som hör till en viss film. Detta gör jag för informationssyfte. Liksom att bara visa vilka genrer en specifik film har.

lubic 2013-06-24 08:38

Nu har jag iofs inte testat, men något liknade detta borde gå att använda:

SELECT q1.id, q1.date, group_concat(genres.name) genre_field FROM
(
SELECT m.id, m.date FROM movies m JOIN movie_genres mg ON mg.movie_id = m.id AND mg.genre_id IN (1, 11) GROUP BY m.id HAVING COUNT(DISTINCT mg.genre_id) = 2
) q1
JOIN movie_genres mg on mg.movie_id = q1.id
JOIN genres ON mg.genre_id = genres.id
GROUP BY q1.id
ORDER BY q1.date ASC

Det går kanske att joina på denna information redan i första frågan, vilket kanske är mer effektivt? Man får helt enkelt testa hur pass bra denna fråga är rent prestandamässigt för att se om det är en möjlig väg att gå.

starstable 2013-06-24 09:18

Citat:

Ursprungligen postat av lubic (Inlägg 20472510)
Nu har jag iofs inte testat, men något liknade detta borde gå att använda:

SELECT q1.id, q1.date, group_concat(genres.name) genre_field FROM
(
SELECT m.id, m.date FROM movies m JOIN movie_genres mg ON mg.movie_id = m.id AND mg.genre_id IN (1, 11) GROUP BY m.id HAVING COUNT(DISTINCT mg.genre_id) = 2
) q1
JOIN movie_genres mg on mg.movie_id = q1.id
JOIN genres ON mg.genre_id = genres.id
GROUP BY q1.id
ORDER BY q1.date ASC

Det går kanske att joina på denna information redan i första frågan, vilket kanske är mer effektivt? Man får helt enkelt testa hur pass bra denna fråga är rent prestandamässigt för att se om det är en möjlig väg att gå.

Den querien du just skrev, är inte optimerad alls, du använder having, vilket innebär att du hämtar ut ALLA rader.

Skriv om, men gör rätt :) Skippa Subqueries till så många delar du kan

lubic 2013-06-24 11:11

Nu tog jag iofs koden med HAVING från kod ovan. Det jag gjorde var att joina på lite tabeller för att hämta ut mer information. Men som sagt, det är kanske inte omöjligt att join på detta på en gång, för att slippa subqueries? Vet dock inte om det är någon märkbar skillnad i prestanda att göra så?

Men du får gärna ge en query som fungerar för att ta fram alla filmer som har två (eller flera) genrer, som då alltså inte använder HAVING på detta sätt. Om det nu skulle ge bättre prestanda, dvs.

Anaxa 2013-06-24 11:28

Citat:

Ursprungligen postat av lubic (Inlägg 20472510)
Nu har jag iofs inte testat, men något liknade detta borde gå att använda:

SELECT q1.id, q1.date, group_concat(genres.name) genre_field FROM
(
SELECT m.id, m.date FROM movies m JOIN movie_genres mg ON mg.movie_id = m.id AND mg.genre_id IN (1, 11) GROUP BY m.id HAVING COUNT(DISTINCT mg.genre_id) = 2
) q1
JOIN movie_genres mg on mg.movie_id = q1.id
JOIN genres ON mg.genre_id = genres.id
GROUP BY q1.id
ORDER BY q1.date ASC

Det går kanske att joina på denna information redan i första frågan, vilket kanske är mer effektivt? Man får helt enkelt testa hur pass bra denna fråga är rent prestandamässigt för att se om det är en möjlig väg att gå.

Det funkade bra :) Ska nog köra på denna tillsvidare :)


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

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