Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [SQL]błąd w sql
Forum PHP.pl > Forum > Przedszkole
agataperz
Witajcie chłopacy,

mam problem stworzyłam zapytanie i na jednym serwerze (do testowania) to działa a na normalnym nie, dlaczego? Co źle zrobiłam?

  1. SELECT a.podgrupa, b.grupa, b.DATA, b.nr_dok, b.dostawca, SUM( b.przychod ) , SUM( b.rozchod ) AS przychod
  2. FROM grupa AS a
  3. CROSS JOIN dostawa AS b
  4. USING ( podgrupa )
  5. WHERE podgrupa = '0004'
  6. AND DATA > curdate( ) - INTERVAL 14
  7. DAY
  8.  


i serwer zwrócił mi zapytanie
MySQL zwrócił komunikat:

#1140 - Mixing of GROUP columns (MIN(),MAX(),COUNT(),...) with no GROUP columns is illegal if there is no GROUP BY clause
kchrapa
Witam!

Patrzac dokladnie : :-)

Generalnie, jest blad logiczny w konstrukcji zapytania. Tzn, umieszczasz
kolumny nie podlegajace agregacji obok funkcji agregujacych - i serwer DB nie jest w stanie dac ci sensownych danych.

Zalozmy, ze masz tabelke:

nazwisko | stan_konta | miasto
Kowalik 333 Warszawa
Maliniak 111 Krakow
Janiak 1341 Warszawa

i chcesz wyswietlic zestawienie : miasto | suma na na kontach:
Powinno byc:

select miasto, sum(stan_konta) from klienci group by miasto;

czyli dostaniesz:
warszawa | 1674
krakow | 111

Ale jesli pominiesz klauzule group by - agregacja wykona sie na wszystkich wierszach,a ty dostaniesz:

warszawa|1785

czyli sume dla wszystkich miast a ta 'warszawa' - to dana z przypadkowego wiersza.

I teraz sedno problemu - taki np. postgres da ci od razu blad skladni, jesli pominiesz group by w zapytaniu,
gdzie masz na liscie kolumn kolumny z agregacja i bez agregacji (rozsadnie - zeby uniknac przypadkowych danych i pomylek.
Np. podane przez ciebie zapytanie wg mnie nie podaje danych o ktore Ci chodzi - i nie zauwazylabys tego, gdyby nie blad skladni ;-)).

Z kolei mysql - przypuszczam ze jest to kwestia ustawionego "SQL mode" w serwerze - tj. w mysql'u mozna stosowac rozne
poziomy restrykcyjnosci/liberalnosci silnika analizujacego zapytanie. Twoj jest pewnie liberalny (domyslnie tak jest), a admin
serwera produkcyjnego pewnie podniosl ten poziom. Tak mi przynajmniej intuicja podpowiada.

Aha - nie jestem pewien - ale CROSS JOIN moze wymusic iloczyn kartezjanski mimo ze podalas warunek zlaczenia przez using()
(trzeba sprawdzic priorytet w dokumentacji ). Proponuje samo JOIN na wszelki wypadek.

Jak podeslesz strukture tabelek i oczekiwany wynik, sproboje Ci pomoc zmodyfikowac zapytanie.


Pozdrawiam serdecznie,
Kacper


==============================
Szkolenia PHP, Warszawa

http://www.AplikacjeInternetowe.pl





agataperz
Będę bardzo wdzięczna smile.gif

a oto struktura tabeli "dostawa":

id | nr _dok | ilosc | cena_jedn | data | podgrupa | grupa | przychod | rozchod | index |
----------------------------------------------------------------------------------------------
1 | 123/09 | 10 | 5.25 |2009-12-01 | 1411 | 15 | 52.50 | 0.00 | 453 |
2 | 523/09 | 50 | 10.00 |2009-12-29 | 1599 | 15 | 500.00 | 0.00 | 853 |
...


struktura tabeli "grupa"

id | nazwa | podgrupa | grupa |
-------------------------------
1 | gazety| 1411 | 15 |
1 | baterie| 1599 | 15 |
.....
kchrapa
A jakie dokladnie zestawienie potrzebujesz? Przykladowa tabelka wynikowa - ;-)
agataperz
wynikiem maja byc wszystkie dostawny z okresu 14 dni z podgrupa=0004


nr_dok | data | SUM(przychod)* | SUM(rozchod)* | grupa | podgrupa | dostawca


* suma danego nr_dok
kchrapa
Witam!

Zapytanko:

SELECT nr_dok,data,sum(przychod) , sum(rozchod) , grupa,podgrupa,dostawca
FROM dostawa
WHERE podgrupa = '0004'
AND data > curdate( ) - INTERVAL 14 DAY
GROUP BY nr_dok,data,grupa,podgrupa,dostawca;

Jesli nie zrobilem literowki - powinno smigac.

Poniewaz na liscie chcesz umiescic tylko nr grupy i podgrupy, zlaczenie tu nie jest potrzebne.
Wszystkie dane sa w tabelce dostawy - wiec nie robilem zlaczenia (chyba,ze kolumna podgrupa
w t. dostawy to inne dane niz podgrupa grupy z tab. grupa albo chcesz wyswietlic nazwe grupy )

Efekt:
- where przefiltruje dane tak jak chcialas (grupa 004 i data)
- group by pogrupuje wg nr_dok i funkcje agregujace dadza wyniki dla kazdej podgrupy

- poniewaz na serwerze docelowym jest wlaczona opcja ONLY_FULL_GROUP_BY
(http://dev.mysql.com/doc/refman/5.1/en/counting-rows.html), mysql wymaga , aby
wszystkie kolumny z listy wyswietlanych (ale nie podlegajace agregacji), zostaly umieszczone
w klauzuli group by - wiec trzeba przeklepac grupa,podgrupa itd

Tutaj ostrzezenie - jesli sie okaze ze na liscie dokumentow beda dwa rekordy z tym samym
nr_dok, ale np. roznymi datami,grupa itd - to group by rozbije wyniki bardziej szczegolowo.

Np. dla danych:

nr_dok | przychod | data
001 10 2010-01-01 16:00
002 5 2010-01-01 15:00
001 8 2010-01-01 16:20
002 6 2010-01-01 15:00

otrzymasz:
002 11 2010-01-01 15:00
001 10 2010-01-01 16:00
001 8 2010-01-01 16:20

Aczkolwiek , raczej nie powinno nic takiego wystapic w tym przypadku, gdyz dany dokument to zawsze
ta sama data, podgrupa jest tylko jedna (po filtracji where'em), grupa - bedzie taka sama dla podgrupy 004
z kazdego wiersza - dostawca przy danym dokumencie tez sie pewnie nie dubluje. Wiec jest oki.

Reasumujac - w twoim zapytaniu brakowalo:
- group by nr_dok (aby funkcje agregujace zliczaly sumy dla kazdego dokumentu oddzielnie)
- z uwagi na wlaczony ONLY_FULL_GROUP_BY na serwerze docelowym, trzeba podac wszystkie kolumny
wyswietlane nie podlegajace agregacji

W sumie to dobrze wyszlo - bo jesli w oryginalnym zapytaniu nie bylo group by nr_dok (nie bylo go w kazdym
razie w poscie od Ciebie ;-) ) a serwer byl w trybie liberalnym - to wynikiem zapytania byl jeden wiersz z suma
wszystkich zamowien danej grupy/intervalu , a nr dokumentu byl losowy - wiec chyba nie ten efekt.
Jak widac , tutaj ten strict przydatny ;-)



Aha - jesli jednak potrzebujesz nazwy grupy:



SELECT d.nr_dok,d.data,sum(d.przychod) , sum(d.rozchod) , d.grupa,g.nazwa,d.podgrupa,d.dostawca
FROM dostawa d JOIN grupa g using(grupa)
WHERE d.podgrupa = '0004'
AND d.data > curdate( ) - INTERVAL 14 DAY
GROUP BY d.nr_dok,d.data,d.grupa,d.podgrupa,d.dostawca,g.nazwa;



Daj znac, czy o to chodzilo i czy zadzialalo - na sucho mogla wpasc jakas literowka ;-)

Pozdrawiam,
Kacper




agataperz
Przepraszam że dopiero teraz odpowiadam ale dopiero wczoraj zmieniłam zapytanie.
Działa super.
Dziękuję
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.