konto usunięte

Temat: Problem z budową zapytania MySQL

Witam serdecznie,
Mam 2 tabele MySQL:

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,
`idserialu` varchar(255) COLLATE utf8_unicode_ci NOT 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 ;



Chciałbym wyświetlić wszystkie rekordy z bazy cms_filmy które dotyczą filmów spełniających następujące warunki:
a) sortowanie filmów od tych które mają najwięcej newsów - do tych które mają najmniej
b) newsy które bierzemy pod uwagę muszą mieścić się w obszarze max 3 miesięcy - licząc od "dzisiaj"
c) jeden news może dotyczyć paru filmów

cms_newsy.idserialu = cms_filmy.bf_id
cms_newsy.idserialu = |nr_id_filmu1|nr_id_filmu2|nr_id_filmu3|nr_id_filmu4|

Próbowałem już różnych sposobów, ale nie mam pojęcia jak mogę to połączyć...

Czy mógłbym prosić o pomoc z tym zapytaniem?

Z góry dziękuję za pomoc,
Łukasz

konto usunięte

Temat: Problem z budową zapytania MySQL

Pokaż jak próbowałeś

Temat: Problem z budową zapytania MySQL

Najpierw to poczytaj sobie jak tworzy się tabele 'jeden do wielu' i 'wiele do wielu'.
Jak już zrobisz poprawnie tabele to poszukaj jak się robi zapytania do takich tabel.
Krzysztof N.

Krzysztof N. CEO. Aplikacje
internetowe i
mobilne. Symfony,
Zend.

Temat: Problem z budową zapytania MySQL

Łukasz P.:
Mam 2 tabele MySQL:

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,
`idserialu` varchar(255) COLLATE utf8_unicode_ci NOT 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 ;



Chciałbym wyświetlić wszystkie rekordy z bazy cms_filmy które dotyczą filmów spełniających następujące warunki:
a) sortowanie filmów od tych które mają najwięcej newsów - do tych które mają najmniej
b) newsy które bierzemy pod uwagę muszą mieścić się w obszarze max 3 miesięcy - licząc od "dzisiaj"
c) jeden news może dotyczyć paru filmów

cms_newsy.idserialu = cms_filmy.bf_id
cms_newsy.idserialu = |nr_id_filmu1|nr_id_filmu2|nr_id_filmu3|nr_id_filmu4|

Próbowałem już różnych sposobów, ale nie mam pojęcia jak mogę to połączyć...

Czy mógłbym prosić o pomoc z tym zapytaniem?
1. Jeśli kolumna / pole
`idserialu` varchar(255) COLLATE utf8_unicode_ci NOT NULL
jest kluczem obcym, to zmień jej typ taki jak posiada klucz główny, tj. na
bigint(20) unsigned
2. (opcjonalnie) Nazewnictwo kolumn / pól również pozostawia wiele do życzenia, ale przyjmijmy, że to drugorzędny problem.

3. W kolejnym kroku zbuduj zapytanie łączące obydwie tabele na podstawie relacji między nimi. Użyj zapytania z słowem kluczowym JOIN. Przykład:
SELECT t1.* FROM tabela1 t1 LEFT JOIN tabela2 t2 ON t1.id = t2.foreign_id
Marcin Mackiewicz

Marcin Mackiewicz Programista JAVA, RS
Adware Polska

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.
Marcin Mackiewicz

Marcin Mackiewicz Programista JAVA, RS
Adware Polska

Temat: Problem z budową zapytania MySQL

Krzysztof N.:

1. Jeśli kolumna / pole
`idserialu` varchar(255) COLLATE utf8_unicode_ci NOT NULL
jest kluczem obcym, to zmień jej typ taki jak posiada klucz główny, tj. na
bigint(20) unsigned

Tylko, że tam celowo zrobione varchar bo programista nie znając zagadnień bazy danych rozwiązuje problem tym czym umie się posługiwać (jakimś językiem programowania) i wymyślił sobie, że rozdzieli dane jakimś znakiem (w tym wypadku |) i w kodzie aplikacji to odpowiednio obsłuży.

To bardzo częsta sytuacja bo jest masa automatów zakładających obiekty w bazach danych które ogłupiają programistę (albo może raczej myślą za niego). Najczęściej zdarza się przy tworzeniu aplikacji działających po web'ie.

Ostatnio dostałem schemat bazy gdzie programista java miał temat z kluczem głównym założonym na dwóch kolumnach. No to w nowej tabeli stworzył kolumnę typu text a następnie wstadził do niej wartość z dwóch kolumn z klucza rozdzieloną "_" i ciachanie tekstu zaszył w kodzie.

Jaka wielka szkoda, że na naszym rynku stanowisko DBA jest nadal mało doceniane ;(
Krzysztof N.

Krzysztof N. CEO. Aplikacje
internetowe i
mobilne. Symfony,
Zend.

Temat: Problem z budową zapytania MySQL

Marcin M.:
Krzysztof N.:

1. Jeśli kolumna / pole
`idserialu` varchar(255) COLLATE utf8_unicode_ci NOT NULL
jest kluczem obcym, to zmień jej typ taki jak posiada klucz główny, tj. na
bigint(20) unsigned

Tylko, że tam celowo zrobione varchar bo programista nie znając zagadnień bazy danych rozwiązuje problem tym czym umie się posługiwać (jakimś językiem programowania) i wymyślił sobie, że rozdzieli dane jakimś znakiem (w tym wypadku |) i w kodzie aplikacji to odpowiednio obsłuży.
Tak, widziałem to. Pominąłem to celowo i świadomie w mojej wypowiedzi.
Marcin M.:
To bardzo częsta sytuacja bo jest masa automatów zakładających obiekty w bazach danych które ogłupiają programistę (albo może raczej myślą za niego).
Tu nie wojsko. Tu myśleć trzeba.

Następna dyskusja:

Problem z MySQL i selectami




Wyślij zaproszenie do