Temat: Problem z budową zapytania MySQL
Zakładam sobie, że w jednej kolumnie (atrybucie) oraz jednym wierszu (krotce) przechowuję tylko jedną informację.
Kolega tutaj usiłuje w kolumnie "idserialu" przechować X informacji co przeczy założeniu.
Wykonuję drobną modyfikację tabeli oraz zakładam tabelę w której będę przechowywał X informacji z kolumny "idserialu":
CREATE TABLE IF NOT EXISTS `cms_newsy` (
`bf_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`tytul` varchar(85) COLLATE utf8_unicode_ci DEFAULT NULL,
`datadodania` datetime NOT NULL,
UNIQUE KEY `id` (`bf_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `cms_filmy` (
`bf_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`tytul` varchar(250) COLLATE utf8_unicode_ci DEFAULT NULL,
UNIQUE KEY `id` (`bf_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `cms_filmy_newsy` (
`film_id` bigint(20) NOT NULL,
`news_id` bigint(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Teraz dodaję troszkę danych testowych:
INSERT INTO cms_filmy(tytul) VALUES ('Kubuś puchatek');
INSERT INTO cms_filmy(tytul) VALUES ('Smerfy');
INSERT INTO cms_filmy(tytul) VALUES ('Muminki');
INSERT INTO cms_filmy(tytul) VALUES ('Gumisie');
INSERT INTO cms_newsy(tytul, datadodania) VALUES ('Lista najlepszych tytułów ostatniego kwartału' ,'2014-01-10');
INSERT INTO cms_newsy(tytul, datadodania) VALUES ('Czy muminek się wreszcie ożeni?' ,'2013-12-15');
INSERT INTO cms_newsy(tytul, datadodania) VALUES ('Smerfy we Francji...' ,'2013-09-10');
INSERT INTO cms_newsy(tytul, datadodania) VALUES ('Modernizacja newsa' ,'2014-01-01');
INSERT INTO cms_filmy_newsy VALUES (1, 1);
INSERT INTO cms_filmy_newsy VALUES (3, 1);
INSERT INTO cms_filmy_newsy VALUES (4, 1);
INSERT INTO cms_filmy_newsy VALUES (2, 3);
INSERT INTO cms_filmy_newsy VALUES (3, 2);
INSERT INTO cms_filmy_newsy VALUES (1, 4);
INSERT INTO cms_filmy_newsy VALUES (2, 4);
INSERT INTO cms_filmy_newsy VALUES (3, 4);
INSERT INTO cms_filmy_newsy VALUES (4, 4);
I teraz z kolegi podpunktów:
a)
-- Suma newsow ogole
SELECT
f.tytul, count(fn.film_id) AS liczba_newsow
FROM
cms_filmy f
LEFT JOIN
cms_filmy_newsy fn ON f.bf_id = fn.film_id
GROUP BY
f.tytul
ORDER BY
liczba_newsow desc, tytul;
b)
-- Suma newsow z ostatnich 3 miesiecy
SELECT
f.tytul, count(fn.film_id) AS liczba_newsow
FROM
cms_filmy f
LEFT JOIN
cms_filmy_newsy fn ON f.bf_id = fn.film_id
JOIN
cms_newsy n ON n.bf_id = fn.news_id
WHERE
n.datadodania >= (now() - interval 3 month)
GROUP BY
f.tytul
ORDER BY
liczba_newsow desc, tytul;
c) Jeden news dla paru filmów oznacza również w drugą stronę, że jeden film może posiadać wiele newsów. Jest to model relacji wiele do wielu obsłużony za pomocą tabeli "cms_filmy_newsy" .
d) Bonus
-- Lista newsow nie starsza niz 3 mies
SELECT
f.*, n.tytul as tytul_newsa, n.datadodania as data_newsa
FROM
cms_filmy f
LEFT JOIN
cms_filmy_newsy fn ON f.bf_id = fn.film_id
JOIN
cms_newsy n ON n.bf_id = fn.news_id
WHERE
n.datadodania >= (now() - interval 3 month);
W mySQL namiętnie nie tworzę. W moim ulubionym PostgreSQL miałbym porobione FOREIGN KEY do tabel z opcją on delete cascade bo wtedy tabela cms_filmy_news byla by automatycznie czyszczona w momencie usuniecia filmu lub newsa. Dorobilbym jeszcze primary key na cms_filmy_newsy albo unique na kolumnach film_id i news_id aby uniknac podwojnych wpisow (przypozadkowan artykulu do filmy.