Galeria w MySQL

Mam dwie tabele w MySQL:

CREATE TABLE `gallery_categories` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`name` VARCHAR( 50 ) NOT NULL ,
`date` DATETIME NOT NULL
) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE TABLE `gallery_pictures` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`category_id` INT NOT NULL ,
`picture` VARCHAR( 20 ) NOT NULL
) ENGINE = MYISAM CHARACTER SET utf8 COLLATE utf8_general_ci;

W pierwszej przetrzymuje informacje dotyczące nazwy i daty utworzenia galerii, a w drugiej nazwy obrazków. To co chciałbym otrzymać po połączeniu tych tabel to tabelka o takiej strukturze:

  • id - id kategorii
  • name - nazwa kategorii
  • picture - obrazek

I to już w zasadzie mam dzięki zapytaniu:

SELECT gallery_categories.id as id, gallery_categories.name as name,
gallery_pictures.picture as picture FROM  gallery_categories JOIN gallery_pictures
ON gallery_categories.id = gallery_pictures.category_id;

Teraz jest problem taki, że potrzebuje dla każdej kategorii tylko trzech obrazków, a z powyższym zapytaniem mam pobierane wszystkie dla danej kategorii. I teraz jak mam obudować tego powyższego selecta żeby mieć tylko po 3 wpisy o danym id.

  • No tak. Z tego co wyczytałem w mysql nie ma funkcji okienkujących, więc zapytanie nie będzie działać. Na bank działa w sqlserver i powinno od jakiegoś czasu działać na postgresie. Na oraclu też powinno, może się trochę składnią różni. W takim wypadku na mysql zostają tylko podzapytania skorelowane z zapytaniem głównym. Coś w stylu:

       SELECT a.id as id, a.name as name,
       b.picture as picture
       FROM  gallery_categories as a JOIN gallery_pictures as b 
       ON gallery_categories.id = gallery_pictures.category_id
       AND b.picture in 
               (SELECT y.picture
                 FROM  gallery_categories as x JOIN gallery_pictures as y 
                 ON gallery_categories.id = gallery_pictures.category_id
                 WHERE x.id = a.id LIMIT 0,3);
    

    Albo jakoś tak ;) Tego typu zapytania nigdy nie były moją dobrą stroną.

  • Może powinieneś użyć klauzuli LIMIT.

     ...LIMIT 0, 3
    

    Od pierwszego przez 3 kolejne.

  • Rozwiązałem problem w zdecydowanie łatwiejszy sposób, mianowicie 2 zapytania ;) Najpierw jedno dla samych nazw kategorii, a potem w pętli zapytanie dla zdjęć kategorii czyli:

    SELECT c.id as id, c.name as name, COUNT(p.picture) as pictures
    FROM gallery_categories as c JOIN gallery_pictures as p ON c.id = p.category_id
    GROUP BY p.category_id
    

    a następnie w pętli:

    SELECT * FROM gallery_pictures WHERE category_id = [kategoria] LIMIT 0, 3
    

    Czasami najprostsze rozwiązania są najlepsze ;)

    Do zamknięcia

  • Z głowy i na szybko więc mogą być błędy ;)

    SELECT * FROM (
       SELECT gallery_categories.id as id, gallery_categories.name as name,
       gallery_pictures.picture as picture,
       ROW_NUMBER() OVER(PARTITION BY gallery_categories.id ORDER BY gallery_categories.id) as rn
       FROM  gallery_categories JOIN gallery_pictures
       ON gallery_categories.id = gallery_pictures.category_id;
    ) as a where a.rn < 4
    

    Oczywiście sprawa dla relacji wiele do wielu będzie bardziej skomplikowana ;)

Zaloguj się, aby dodać swoją odpowiedź