[SQL] DISTINCT lub GROUP BY - problem ze złożonym zapytaniem

0

Witam,
Posiadam zapytanie:

SELECT t.ID_TOWARU, dmp.CENA AS CENA_ZAKUPU_NETTO, ct.CENA AS CENA_SPRZEDAZY_BRUTTO,
t.NAZWA_VAT_SPRZED AS VAT FROM towary t JOIN DOK_MAGAZYNOWE_POZ dmp
on t.ID_TOWARU = dmp.ID_TOWARU JOIN DOK_MAGAZYNOWE dm ON dm.ALT_DOK_MAG = dmp.ALT_DOK_MAG 
JOIN CENY_TOWAROW ct on dmp.ID_TOWARU = ct.ID_TOWARU JOIN AKT_STAN_MAG asm 
on ct.ID_TOWARU = asm.ID_TOWARU WHERE (dmp.ID_TOWARU = 002070 or dmp.ID_TOWARU = 002071)
and asm.ILOSC > 0 and (dm.SYMBOL_KWITU = 'PZ' OR dm.SYMBOL_KWITU = 'PZF') AND ct.ID_GRUPY_CEN = 2 ORDER BY t.ID_TOWARU ASC, dm.DATA_UTWORZENIA DESC

I otrzymuje rekordy:
ID_TOWARU, CENA_ZAKUPU_NETTO, CENA_SPRZEDAZY_BRUTTO, NAZWA_VAT_SPRZED
002070 90.6500 139.00 22%
002070 90.6500 139.00 22%
002070 87.2200 139.00 22%
002070 87.2200 139.00 22%
002070 95.0600 139.00 22%
002070 95.0600 139.00 22%
002070 93.1000 139.00 22%
002070 93.1000 139.00 22%

002071 110.7400 179.00 22%
002071 110.7400 179.00 22%
002071 110.7400 179.00 22%
002071 122.5000 179.00 22%
002071 122.5000 179.00 22%
002071 122.5000 179.00 22%
002071 104.0000 179.00 22%
002071 104.0000 179.00 22%

Natomiast chciałbym to przerobić tak, by wyniki wyglądały tak:
002070 90.6500 139.00 22%
002071 110.7400 179.00 22%

Czyli dla ID ma się nie powtarzać, a z powyższych wyników ma brać sobie pierwszy rekord.
Wedle tego zapytania, pierwszy wynik dla ID to ten z najświeższą datą, inne mnie nie obchodzą.

Próbowałem dodać DISTINCT:

SELECT DISTINCT t.ID_TOWARU, dmp.CENA AS CENA_ZAKUPU_NETTO, ct.CENA AS CENA_SPRZEDAZY_BRUTTO,
t.NAZWA_VAT_SPRZED AS VAT FROM towary t JOIN DOK_MAGAZYNOWE_POZ dmp
on t.ID_TOWARU = dmp.ID_TOWARU JOIN DOK_MAGAZYNOWE dm ON dm.ALT_DOK_MAG = dmp.ALT_DOK_MAG 
JOIN CENY_TOWAROW ct on dmp.ID_TOWARU = ct.ID_TOWARU JOIN AKT_STAN_MAG asm 
on ct.ID_TOWARU = asm.ID_TOWARU WHERE (dmp.ID_TOWARU = 002070 or dmp.ID_TOWARU = 002071)
and asm.ILOSC > 0 and (dm.SYMBOL_KWITU = 'PZ' OR dm.SYMBOL_KWITU = 'PZF') AND ct.ID_GRUPY_CEN = 2 ORDER BY t.ID_TOWARU ASC, dm.DATA_UTWORZENIA DESC

Error: ORDER BY items must appear in the select list if SELECT DISTINCT is specified.

Próbowałem dodać Group By:

SELECT t.ID_TOWARU, dmp.CENA AS CENA_ZAKUPU_NETTO, ct.CENA AS CENA_SPRZEDAZY_BRUTTO,
t.NAZWA_VAT_SPRZED AS VAT FROM towary t JOIN DOK_MAGAZYNOWE_POZ dmp
on t.ID_TOWARU = dmp.ID_TOWARU JOIN DOK_MAGAZYNOWE dm ON dm.ALT_DOK_MAG = dmp.ALT_DOK_MAG 
JOIN CENY_TOWAROW ct on dmp.ID_TOWARU = ct.ID_TOWARU JOIN AKT_STAN_MAG asm 
on ct.ID_TOWARU = asm.ID_TOWARU WHERE (dmp.ID_TOWARU = 002070 or dmp.ID_TOWARU = 002071)
and asm.ILOSC > 0 and (dm.SYMBOL_KWITU = 'PZ' OR dm.SYMBOL_KWITU = 'PZF') AND ct.ID_GRUPY_CEN = 2 GROUP BY t.ID_TOWARU ORDER BY t.ID_TOWARU ASC, dm.DATA_UTWORZENIA DESC

Column 'DOK_MAGAZYNOWE_POZ.CENA' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

No dobra, ale jaką aggregate function jestem w stanie dać dla ceny? First() nie działa.

0

Min()

0

podaj DDL tabel

0

No tak, ale min wybiera minimalną, tak jak max wybieram maksymalną

SELECT t.ID_TOWARU, max(dmp.CENA) AS CENA_ZAKUPU_NETTO, max(ct.CENA) AS CENA_SPRZEDAZY_BRUTTO,
min(t.NAZWA_VAT_SPRZED) AS VAT FROM towary t JOIN DOK_MAGAZYNOWE_POZ dmp
ON t.ID_TOWARU = dmp.ID_TOWARU JOIN DOK_MAGAZYNOWE dm ON dm.ALT_DOK_MAG = dmp.ALT_DOK_MAG
JOIN CENY_TOWAROW ct ON dmp.ID_TOWARU = ct.ID_TOWARU JOIN AKT_STAN_MAG asm
ON ct.ID_TOWARU = asm.ID_TOWARU WHERE (dmp.ID_TOWARU = 002070 OR dmp.ID_TOWARU = 002071)
AND asm.ILOSC > 0 AND (dm.SYMBOL_KWITU = 'PZ' OR dm.SYMBOL_KWITU = 'PZF') AND ct.ID_GRUPY_CEN = 2 GROUP BY t.ID_TOWARU ORDER BY t.ID_TOWARU ASC, min(dm.DATA_UTWORZENIA) DESC
002070	95.0600	139.00	22%
002071	122.5000	179.00	22%

DDL?
MSSQL Studio nie pozwala mi zrobić Create'a co by poznać strukturę tabeli, brak uprawnień.

Skoro nie ma niczego takiego jak FIRST() to muszę PHP-kiem przejechać po ID_TOWARU i następnie wygenerować kolejne zapytania? Bez sensu.

0

To może inaczej, dam prosty przykład.
Mam tabelę SPRZEDAZ z polami ID_TOWARU, CENA, DATA_SPRZEDAZY.

W tabeli powtarzają się ID_TOWARU, jednak mają różne pola CENA i DATA_SPRZEDAZY.
Chciałbym wybrać z tej tabeli cenę i ID_TOWARU (niepowtarzające się), a warunkiem niepowtarzania była by ostatnia DATA_SPRZEDAZY dla danego ID_TOWARU.

W powyższym zapytaniu jest od cholery JOIN-ów, które tylko przeszkadzają w analizie zapytania.

Czyli ja to widziałem tak by ORDER BY posortować wyniki po ID_TOWARU rosnąco, a potem DATA_SPRZEDAZY malejąco.
Następnie GROUP BY dla ID_TOWARU (tak by się nie powtarzały).
Brakuje tylko Aggregate function dla CENY, no i przecież nie mogę dać AVG, MIN, MAX, bo ja chce konkretną wartość z brzegu.

0

Coś w ten deseń:
SELECT t1.ID_TOWARU, t1.DATA_SPRZEDAZY, t1.CENA FROM SPRZEDAZ t1 JOIN (SELECT ID_TOWARU, MAX(DATA_SPRZEDAZY) DATA_SPRZEDAZY FROM SPRZEDAZ GROUP BY ID_TOWARU) t2 ON t1.ID_TOWARU=t2.ID_TOWARU AND t1.DATA_SPRZEDAZY=t2.DATA_SPRZEDAZY

Co wcale nie znaczy, że pozbędziesz się duplikatów.

pozdrawiaMM

0

Dziękuje bardzo. Wyszło bardzo ładnie w ten deseń. Zapytanie wyszło kolosalne, ale działa ;).
I nie ma duplikatów, bo nie ma 2 rekordów z takim samym ID_TOWARU i czasem jednocześnie.

Jeszcze kolejne pytanie chciałbym wybrać ID_TOWARU, dla którego MARZA jest powiedzmy największa, albo najmniejsza.
Utrudnieniem jest (a może i nie) fakt, że MARZA to nie pole tabeli, tylko wartość wyliczana z 2 kolumn.

Niestety w ten sposób się nie da:

SELECT ID_TOWARU, max(CENA_ZAKUPU/CENA_SPRZEDAZY) as MARZA FROM TOWARY

Jak to zrobić?

0 użytkowników online, w tym zalogowanych: 0, gości: 0