konto usunięte

Temat: Problem z duplikatami w zapytaniu MySQL

Witam serdecznie,
Mam takie zapytanie MySQL:


SELECT cms_uslugi.*, `cms_grupy_uzytkownikow`.bf_id AS grupa FROM cms_uslugi LEFT OUTER JOIN `cms_uslugipracownikow` ON (`cms_uslugi`.`bf_id` = `cms_uslugipracownikow`.`bf_iduslugi`) LEFT OUTER JOIN `cms_users` ON (`cms_uslugipracownikow`.`bf_idusers` = `cms_users`.`bf_id`)
LEFT OUTER JOIN `cms_grupy_uzytkownikow` ON (`cms_users`.`grupy_uzytkownikow` = `cms_grupy_uzytkownikow`.`bf_id` OR `cms_users`.`grupy_uzytkownikow2` = `cms_grupy_uzytkownikow`.`bf_id`) WHERE cms_uslugi.enable='1' AND (cms_users.grupy_uzytkownikow = 20 OR cms_users.grupy_uzytkownikow2 = 20 )AND cms_uslugi.bf_idfilia='12' AND cms_users.filia = 12 GROUP BY cms_uslugi.bf_id, grupa ORDER BY nazwa ASC


problem w tym,że przy większej ilości danych zapytanie to zwraca mi duplikaty.... :( duplikaty można odseparować po dublującym się bf_id....
nie bardzo wiem jak zapisać taki filtr... Macie może jakiś pomysł?

Z góry dziękuje za pomoc,
Łukasz
Jacek R.

Jacek R. programista

Temat: Problem z duplikatami w zapytaniu MySQL

Absrahując od tych JOINów, które wydają się nadmiarowe, ale nie znam schematu bazy, przede wszystkim masz błędy merytoryczne w tym zapytaniu.

1. Używanie grupowania bez funkcji agregujących jest bez sensu, bo nic nie daje. W ogóle zawsze mnie dziwiło, że MySQL pozwala grupować bez agregacji, bo to tylko powoduje takie błędy jak tutaj. Jeśli grupujesz po czymś, a reszty nie agregujesz, to w jaki sposób ta reszta ma zostać wybrana? Ma się losować dowolna wartość z tych innych kolumn, czy jak?

2. Jeśli grupujesz po jednej kolumnie, to fakt, tworzysz w niej unikalne wartości. Ale jeśli robisz to po dwóch kolumnach, to tworzysz unikalne zestawy danych z tych dwóch kolumn. Dlatego sama kolumna "cms_uslugi.bf_id" nie będzie w takim wyniku unikalna, unikalny będzie zestaw "cms_uslugi.bf_id" i "grupa" (na przykład 1 i 1, 1 i 2, 1 i 3, 2 i 1, 2 i 2, 2 i 3...).

Poza tym pytanie, czy "grupa" i "cms_uslugi.bf_id" to nie jest to samo? Nazwa przed aliasowaniem wskazuje, że tak (a jeśli nie, to schemat jest fatalnie zaprojektowany), a w takim razie grupujesz podwójnie po tym samym, więc poprawne (wg MySQLowej filozofii) grupowanie będziesz mieć na ostatniej kolumnie, czyli "grupa" (i to tam nie będzie duplikatów).
Jakub L.

Jakub L. Programista

Temat: Problem z duplikatami w zapytaniu MySQL

Zapytanie jest tldr, ale czy select distinct nie zadziała?

konto usunięte

Temat: Problem z duplikatami w zapytaniu MySQL

.... aha.... ;-) mógłbyś mi w takim razie napisać jak powinno wyglądać takie zapytanie?
mam takie dane: http://mybutterfly.website.pl/baza.txt :) czyli generalnie to zapytanie się do niczego nie nadaje?:(

konto usunięte

Temat: Problem z duplikatami w zapytaniu MySQL

nudziło mi się i:
1. zrobiłem twoje zapytanie na twojej bazie danych i nie dubluje wyników.

31 12 azxc 0 1 0 0 23 2 1bedhjlrpyy108 1 22
31 12 azxc 0 1 0 0 23 2 1bedhjlrpyy108 1 20
29 12 Lekcja 60 min z dojazdem 0 1 0 0 25 1 1aggjhmnuyy121 1 22
29 12 Lekcja 60 min z dojazdem 0 1 0 0 25 1 1aggjhmnuyy121 1 20

wyniki różnią się numerem grupy na końcu . tak więc select distinct zwróci to samo.

2. mieszasz nazwę pracownik z user co powoduje zaciemnienie tego co chcesz zrobić.
np. tabela cms_uslugipracownikow
ma pola bf_iduslugi, bf_idusers

3. skoro możesz mieć kilka usług przypisanych do jednego pracownika i kilku pracowników do jednej grupy to chyba oczywiste że w takim zapytaniu będziesz miał powtarzające się usługi.

jak chcesz sprawdzić jakie masz usługi to zrób select tylko na tabeli usługi. a jak chcesz wiedzieć jakie ma usługi dany użytkownik to select powinien być na tabeli usługi i cms_uslugipracownikow itd.

4. powód dla którego masz w wynikach grupę 20 i 22, jest taki że masz :
(cms_users.grupy_uzytkownikow = 20 OR cms_users.grupy_uzytkownikow2 = 20 )

tak więc grupa_uzytkownikow=22, to pozycja spełniająca warunek grupa_uzytkownikow2 = 20Krzysztof D. edytował(a) ten post dnia 30.06.12 o godzinie 11:04

konto usunięte

Temat: Problem z duplikatami w zapytaniu MySQL

tak, ale ja bym chcial filtrować po 1 kolumnie wyników: 31, 31 i 29 , 29 :)

tamte duplikaty mi przeszkadzają ;)
Jacek R.

Jacek R. programista

Temat: Problem z duplikatami w zapytaniu MySQL

Ale co chcesz filtrować? Problem nie jest w zapytaniu (jest w całej bazie, ale to inna bajka), tylko w Twoim podejściu.

Opieram się na wyniku z góry:
31 12 azxc 0 1 0 0 23 2 1bedhjlrpyy108 1 22
31 12 azxc 0 1 0 0 23 2 1bedhjlrpyy108 1 20
29 12 Lekcja 60 min z dojazdem 0 1 0 0 25 1 1aggjhmnuyy121 1 22
29 12 Lekcja 60 min z dojazdem 0 1 0 0 25 1 1aggjhmnuyy121 1 20

Przeszkadzają Ci powtórzenia w pierwszej kolumnie. Czyli chcesz zostawić tylko jeden wiersz dla każdej unikalnej pierwszej kolumny. Więc pytanie za 100 punktów:

Zostawiasz to:
31 12 azxc 0 1 0 0 23 2 1bedhjlrpyy108 1 22

Czy zostawiasz to:
31 12 azxc 0 1 0 0 23 2 1bedhjlrpyy108 1 20

Po co Ci ostatnia kolumna doklejona do tego zestawu, skoro nie wiesz, na jakiej zasadzie chcesz ją mieć wybraną? Nie ma ona znaczenia, więc po prostu ją wytnij. Jak się pozbędziesz grupowania po "grupa", zmniejszysz wielkość grupy do bf_id i będziesz mieć wyniki unikalne dla tej pierwszej kolumny. Ale pisałem to już wyżej.

Albo inaczej: powiedz co dokładnie chcesz osiągnąć. Tylko nie mów, że coś takiego jak wyżej, ale bez zduplikowanej pierwszej kolumny :P Podejście masz złe (grupowanie bez agregacji), więc powiedz co chcesz uzyskać, a pokażę Ci, jak napisać do tego poprawne zapytanie.

konto usunięte

Temat: Problem z duplikatami w zapytaniu MySQL

super,dziekuje :)

generalnie jest baza która zawiera pracowników, file, umiejętności itp.

Powyższe zapytanie wyświetla między innymi umiejętności pracowników według klucza.
1 pracownik może być w paru grupach (gdyby nie było : OR `cms_users`.`grupy_uzytkownikow2` = `cms_grupy_uzytkownikow`.`bf_id` - to byłoby okey). Problem pojawił się w momencie gdy 1 pracownik trafił do paru grup - zaczęły się zdublowane rekordy... :( i właśnie nie bardzo wiem jak to przeskoczyć ://

konto usunięte

Temat: Problem z duplikatami w zapytaniu MySQL

nie zmieniając bazy i zapytania zbytnio:

SELECT distinct cms_uslugi.* FROM cms_uslugi LEFT OUTER JOIN `cms_uslugipracownikow` ON (`cms_uslugi`.`bf_id` = `cms_uslugipracownikow`.`bf_iduslugi`) LEFT OUTER JOIN `cms_users` ON (`cms_uslugipracownikow`.`bf_idusers` = `cms_users`.`bf_id`)
LEFT OUTER JOIN `cms_grupy_uzytkownikow` ON (`cms_users`.`grupy_uzytkownikow` = `cms_grupy_uzytkownikow`.`bf_id` OR `cms_users`.`grupy_uzytkownikow2` = `cms_grupy_uzytkownikow`.`bf_id`) WHERE cms_uslugi.enable='1' AND (cms_users.grupy_uzytkownikow = 20 OR cms_users.grupy_uzytkownikow2 = 20 )AND cms_uslugi.bf_idfilia='12' AND cms_users.filia = 12 ORDER BY nazwa ASC

powyższe zapytanie nadal jest do d. ale robi chyba co chcesz otrzymać. jak nie to chyba nie mam pojęcia co chcesz zrobić. możesz ew. mieć tą grupę w wynikach, ale wtedy tylko jedna usługa losowo byłaby wyświetlana.

na pewno powinieneś ujednolicić nazewnictwo, dodać tablicę łączącą użytkowników z grupami.
Jacek R.

Jacek R. programista

Temat: Problem z duplikatami w zapytaniu MySQL

Jeśli chcesz mieć w wyniku podział na grupy, to wpisy będą się powtarzać, jeśli ktoś jest w kilku grupach. To jest logiczne i wynika z podziału na grupy. Po prostu w ogóle tych grup nie uwzględniaj w wyniku, jeśli są niepotrzebne. Wystarczy użyć ich do filtrowania.

Tutaj masz przykład wybrania nazwy usługi i nazwy użytkownika, filtrując po jego filii oraz jego wszystkich grupach (bez sensu, że też grupa jest przypisana do filii, pominąłem to). Nie ma tu żadnego grupowania, jeśli chcesz wyjąć dodatkowe dane, rozszerz sobie SELECTa.

SELECT cms_users.nazwa AS nazwa_uzytkownika, cms_uslugi.nazwa AS nazwa_uslugi FROM cms_users
LEFT JOIN cms_uslugipracownikow ON cms_users.bf_id = cms_uslugipracownikow.bf_idusers
LEFT JOIN cms_uslugi ON cms_uslugipracownikow.bf_iduslugi = cms_uslugi.bf_id
WHERE cms_uslugi.enable = '1' AND
cms_users.filia = 12 AND
(cms_users.grupy_uzytkownikow = 20 OR
cms_users.grupy_uzytkownikow2 = 20 OR
cms_users.grupy_uzytkownikow3 = 20 OR
cms_users.grupy_uzytkownikow4 = 20 OR
cms_users.grupy_uzytkownikow5 = 20 OR
cms_users.grupy_uzytkownikow6 = 20 OR
cms_users.grupy_uzytkownikow7 = 20 OR
cms_users.grupy_uzytkownikow8 = 20 OR
cms_users.grupy_uzytkownikow9 = 20 OR
cms_users.grupy_uzytkownikow10 = 20)

Najlepiej przenieść zależność użytkownik-grupa do oddzielnej tabeli, a nie rozszerzać tak głupio tabele z użytkownikami (grupa1, grupa2, ..., grupa10). Co jak dojdzie 11 grupa dla użytkownika? Będziesz zmieniać schemat bazy i zapytania?

konto usunięte

Temat: Problem z duplikatami w zapytaniu MySQL

problem w tym ze bazy nie bardzo moge ruszac:(

Twoje zapytanie nie do konca dziala... nie zwraca wszystkich potrzebnych mi danych...:/

moge sie odezwac do Ciebie jakos na PRIV?

konto usunięte

Temat: Problem z duplikatami w zapytaniu MySQL

a wiesz w ogóle co ma to zapytanie zwrócić ?
jeśli tak to napisz oczekiwany wynik po prostu pisząc go. powyżej masz wynik oryginalnego zapytania dla ułatwienia.Krzysztof D. edytował(a) ten post dnia 01.07.12 o godzinie 03:00
Marcin Mackiewicz

Marcin Mackiewicz Programista JAVA, RS
Adware Polska

Temat: Problem z duplikatami w zapytaniu MySQL

Wiesz w sumie podstawowy błąd to zapisanie tej samej informacji na kilku atrybutach. Przecież przynależność do grupy to rodzaj informacji. Sama informacja powinna być przechowywana w krotkach (wierszach).
Pała dla osoby projektującej te bazę.
Skoro zmieniamy zależność mówiącą o przynależności użytkownika do grupy z 1:1 na 1:n to niezbędne jest dodanie tabeli przechowującej listę grup do których należy użytkownik.

Jeżeli tego nie poprawisz to z tego co kojarze z teoretyki poziom złożoności zapytań będzie mocno rósł. Nie wspomnę już o czasie ich wykonywania oraz potrzebnych do tego zasobach sprzętowych.

Najgorsze jednak jest to, że ilość grup jest ograniczona z góry do 2 i każdorazowe zwiększenie tego ograniczenia spowoduje, że będziesz musiał przepisywać wszystkie zapytania które wykorzystujesz.

Dodatkowa tabela, że nie będziesz musiał się tym zajmować w przyszłości. Nie powiem aby to posprzątać to trochę pracy jest ale po jej wykonaniu nie wrócisz do tego tematu już nigdy :)

Jeżeli jednak nie możesz zmieniać bazy to dodaj te tabele i przepisuj informacje z tych pól do tabeli (zestaw wyzwalaczy) tak abyś mógł pisać prostsze zapytania do bazy. Musisz tylko pamiętać aby a źródłowej tabeli wprowadzić ograniczenie takie, że: id_grupy1 <> id_grupy2Marcin Mackiewicz edytował(a) ten post dnia 30.06.12 o godzinie 19:10



Wyślij zaproszenie do