Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

 
Reply to this topicStart new topic
> [MySQL]Grupowanie wg. masek z innej tabeli
timon27
post
Post #1





Grupa: Zarejestrowani
Postów: 578
Pomógł: 69
Dołączył: 15.04.2007
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Posiadam dwie tabele w mysql.
Tabela towarów:
  1. NAZWA CENA
  2. krem jkiśtam 2,4
  3. krem cośtam 1,5
  4. szampon cośtam 3,4
  5. szampon cośtam2 3,5

oraz początków nazw - identyfikująca rodzaj produktu:
  1. MASKA
  2. krem
  3. szampon

Chciałbym pogrupować pierszą tabelę wg początków nazw z drugiej.
(kolumna 'cena' jest tylko po to aby pokazać że grupowanie nie jest bezsensowne).
Jakieś pomysły?
Pierwszej tabeli nie mogę edytować.

Żeby nie było: mysql znam, nie radzę sobie tylko ze zmienną długością masek.
Gdyby wszystkie maski miały tą samą długość nie miałbym problemu:
  1. SELECT * FROM
  2. (SELECT *,SUBSTR(nazwa,1,5) AS maska FROM towary) AS first
  3. JOIN maski
  4. ON maski.maska=first.maska
  5. GROUP BY maski.maska


Ten post edytował timon27 7.05.2013, 09:20:58
Go to the top of the page
+Quote Post
mortus
post
Post #2





Grupa: Zarejestrowani
Postów: 2 178
Pomógł: 596
Dołączył: 25.09.2009
Skąd: Piwniczna-Zdrój

Ostrzeżenie: (0%)
-----


Bardzo dziwne podejście i w ogóle nieoptymalne. Taki rodzaj produktu powinien być chyba czymś w stylu kategorii. Niemniej da się to zrobić, choć nie wiem po co to złączenie.
  1. SELECT `temp`.`t_maska` `maska`, SUM(`temp`.`t_cena`) `cena_razem` FROM (
  2. SELECT SUBSTRING_INDEX(`t`.`nazwa`, ' ', 1) `t_maska`, `t`.`cena` `t_cena` FROM `towary` `t`
  3. ) `temp`
  4. LEFT JOIN `maski` `m` ON `temp`.`t_maska` = `m`.`maska`
  5. GROUP BY `m`.`maska`

Dać się da, ale nie polecam i radzę się dobrze zastanowić nad funkcjonalnością aplikacji i strukturą bazy danych.

Ten post edytował mortus 7.05.2013, 10:01:55
Go to the top of the page
+Quote Post
timon27
post
Post #3





Grupa: Zarejestrowani
Postów: 578
Pomógł: 69
Dołączył: 15.04.2007
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Struktura baz danych pochodzi z programu kasowego.
Program nie jest mojego autorstwa, nie mam mozliwości ani prawa jego modyfikacji.

Zapytanie niestety działa tylko jeśli po masce jest spacja.
Niestety mam też inne sytuacje:
  1. NAZWA CENA
  2. krem jkiśtam 2,4
  3. krem cośtam 1,5
  4. cośtam 1,2
  5. cośinnego 3,4


  1. MASKA
  2. krem
  3. coś


Ten post edytował timon27 7.05.2013, 10:32:00
Go to the top of the page
+Quote Post
mortus
post
Post #4





Grupa: Zarejestrowani
Postów: 2 178
Pomógł: 596
Dołączył: 25.09.2009
Skąd: Piwniczna-Zdrój

Ostrzeżenie: (0%)
-----


Najgorszym z możliwych rozwiązań jest takie złączenie:
  1. SELECT `m`.`maska`, SUM(`t`.`cena`) FROM `towary` `t`, `maski` `m`
  2. WHERE LOCATE(`m`.`maska`, `t`.`nazwa`) = 1
  3. GROUP BY `m`.`maska`


Najbardziej optymalnym i w dodatku bezinwazyjnym (nie trzeba modyfikować czyjejś aplikacji) rozwiązaniem wydaje się być utworzenie trzeciej tabeli maski_towarow zawierającej jedynie dwie kolumny id_maski i id_towaru, obie będące kluczem głównym. Później jednorazowym zapytaniem
  1. INSERT INTO `maski_towarow` SELECT `m`.`id`, `t`.`id` FROM `maski` `m`, `towary` `t` WHERE LOCATE(`m`.`maska`, `t`.`nazwa`) = 1

uzupełniamy tabelę maski_towarow i w naszej "części" aplikacji korzystamy właśnie z niej:
  1. SELECT `m`.`maska`, SUM(`t`.`cena`) FROM `maski` `m`
  2. LEFT JOIN `maski_towarow` `mt` ON `m`.`id` = `mt`.`id_maski`
  3. LEFT JOIN `towary` `t` ON `mt`.`id_towaru` = `t`.`id`
  4. GROUP BY `m`.`id`
Go to the top of the page
+Quote Post
timon27
post
Post #5





Grupa: Zarejestrowani
Postów: 578
Pomógł: 69
Dołączył: 15.04.2007
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Cytat(mortus @ 7.05.2013, 12:28:08 ) *
utworzenie trzeciej tabeli maski_towarow zawierającej jedynie dwie kolumny id_maski i id_towaru

Jak niby mam to zrobić ?
Przed każdym wywołaniem zapytania (o które pytam w tym wątku) mam tworzyć tę tabelę?
To dopiero będzie nieoptymalne.
Bo nie wyobrażam sobie monitorować w czasie rzeczywistym
czy ktoś właśnie nie dodaje towarów do tabeli
aby uzupełnić tabelę powiązań.

Cytat(mortus @ 7.05.2013, 12:28:08 ) *
LOCATE(nazwa,maska)=1

Dokładnie o to mi chodziło.
Czas wykonania 3 sekundy
(kilkanaście tysięcy towarów, setka masek)
- akceptowalny przy własnych zestawieniach,
choć faktycznie nieakceptowalne gdybym potrzebował to ze strony klientów.

Ten post edytował timon27 7.05.2013, 11:55:41
Go to the top of the page
+Quote Post
mortus
post
Post #6





Grupa: Zarejestrowani
Postów: 2 178
Pomógł: 596
Dołączył: 25.09.2009
Skąd: Piwniczna-Zdrój

Ostrzeżenie: (0%)
-----


No ale jeśli ktoś dodaje towar to i musi podać powiązaną z nim maskę, a to wszystko możemy dzięki TRIGGER-om wpakować do naszej tabeli maski_produktow (tę tabelę tworzymy i uzupełniamy tylko raz istniejącymi danymi, a później już na bieżąco danymi wprowadzonymi przez użytkownika).

Nie ma potrzeby modyfikowania czegokolwiek w istniejącej już aplikacji.

Ten post edytował mortus 7.05.2013, 12:00:43
Go to the top of the page
+Quote Post
timon27
post
Post #7





Grupa: Zarejestrowani
Postów: 578
Pomógł: 69
Dołączył: 15.04.2007
Skąd: Wrocław

Ostrzeżenie: (0%)
-----


Cytat(mortus @ 7.05.2013, 12:57:47 ) *
No ale jeśli ktoś dodaje towar to i musi podać powiązaną z nim maskę


Nie, nie nie musi. Skąd pomysł że musi?
Miałby wychodzić z programu, aby go gdzieś podać?
Jeśli dodaje się nowy RODZAJ towaru, to wtedy tak, ale to się dziej bardzo rzadko.

Cytat(mortus @ 7.05.2013, 12:57:47 ) *
a później już na bieżąco danymi wprowadzonymi przez użytkownika


No ale w jaki sposób? Mam przechwytywać dodawanie towarów do bazy? To będzie niemożliwe.
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
2 Użytkowników czyta ten temat (2 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Aktualny czas: 23.08.2025 - 17:56