Forum Użytkownikow Subiekt GT
InsERT GT => Dodatki - zestawienia - sfera => Wątek zaczęty przez: kkot92 w Październik 25, 2018, 14:47:14
-
Witam serdecznie,
jest to mój pierwszy post na forum więc jeśli zrobię coś nie tak to proszę o wyrozumiałość :) forum przeglądam już od dłuższego czasu, ale do tej pory (kiedy zacząłem bawić się SQL-em) nie było potrzeby wypowiadania się.
Ostatnio odkryłem potencjał drzemiący w zestawieniach SQL i zainspirowało mnie to do nauki tego języka. Mam za sobą kilka prostych zestawień (tak, działają :D), ale problem pojawił się przy próbie napisania czegoś bardziej złożonego - oczywiście dla mnie, bo wiem że dla "wyjadaczy" z forum to pewnie pestka.
Przechodząc do konkretów - chciałem napisać zestawienie, które pokazuje aktualną ilość towarów o stanie niezerowym dla każdego magazynu osobno. Wyszło mi coś takiego
SELECT
tw__Towar.tw_Nazwa AS [Nazwa towaru] FROM tw__Towar,
SUM((tw_Stan.st_Stan) AS [UR] FROM tw_Stan WHERE tw_Stan.st_MagId=1 ),
SUM((tw_Stan.st_Stan) AS [ŁP] FROM tw_Stan WHERE tw_Stan.st_MagId=5 ),
SUM((tw_Stan.st_Stan) AS [KJ] FROM tw_Stan WHERE tw_Stan.st_MagId=6 ),
SUM((tw_Stan.st_Stan) AS [PZ] FROM tw_Stan WHERE tw_Stan.st_MagId=7 ),
SUM((tw_Stan.st_Stan) AS [MS] FROM tw_Stan WHERE tw_Stan.st_MagId=8 ),
SUM((tw_Stan.st_Stan) AS [MJ] FROM tw_Stan WHERE tw_Stan.st_MagId=9 ),
SUM((tw_Stan.st_Stan) AS [NP] FROM tw_Stan WHERE tw_Stan.st_MagId=10 ),
SUM((tw_Stan.st_Stan) AS [ŁĄCZNIE] FROM tw_Stan WHERE tw_Stan.st_MagId IN ('1','5','6','7','8','9','10'))
FROM tw__Towar, tw_Stan WHERE tw_Stan.st_TowId=tw__Towar.tw_Id AND tw_Stan.st_Stan>0
GROUP BY tw__Towar.tw_Nazwa
Jest to ostatnia wersja zapytania, którą próbowałem przerabiać (było już wiele prób przeróbki, jednak żadna właściwa). Co w powyższym zapytaniu napisałem źle? Jeśli daję argumenty dla SUM w nawiasie, to program zwraca mi błąd przy wyrażeniu AS.
Oczywiście powyższe zapytanie utworzyłem na bazie wcześniej napisanego tj.
SELECT
tw__Towar.tw_Nazwa AS [Nazwa towaru],
SUM(tw_Stan.st_Stan) AS [ŁĄCZNIE]
FROM tw__Towar, tw_Stan WHERE tw_Stan.st_MagId IN ('1','5','6','7','8','9','10') AND tw_Stan.st_TowId=tw__Towar.tw_Id AND tw_Stan.st_Stan>0
GROUP BY tw__Towar.tw_Nazwa
Powyższe zapytanie dla jednego magazynu zwraca rekordy, natomiast złożone już nie. Gdzie robię błąd?
-
Nie możesz używać FROM przy każdej kolumnie (nie w ten sposób).
W tym przypadku możesz użyć na przykład CASE WHEN ELSE END:
SELECT
tw__Towar.tw_Nazwa AS [Nazwa towaru] ,
SUM(CASE WHEN tw_Stan.st_MagId = 1 THEN tw_Stan.st_Stan ELSE 0 END) [UR],
SUM(tw_Stan.st_Stan) AS [ŁĄCZNIE]
FROM tw__Towar, tw_Stan WHERE tw_Stan.st_MagId IN (1,5,6,7,8,9,10) AND tw_Stan.st_TowId=tw__Towar.tw_Id AND tw_Stan.st_Stan>0
GROUP BY tw__Towar.tw_Nazwa
W warunku tw_Stan.st_MagId nie potrzebnie użyłeś apostrofów (kolumna jest typu liczbowego).
Zamiast podawać za każdym razem nazwę tabeli możesz użyć aliasów:
SELECT
tw.tw_Nazwa AS [Nazwa towaru] ,
SUM(CASE WHEN st.st_MagId = 1 THEN st.st_Stan ELSE 0 END) [UR],
SUM(st.st_Stan) AS [ŁĄCZNIE]
FROM tw__Towar tw , tw_Stan st WHERE st.st_MagId IN (1,5,6,7,8,9,10) AND st.st_TowId=tw.tw_Id AND st.st_Stan>0
GROUP BY tw.tw_Nazwa
-
Co w powyższym zapytaniu napisałem źle?
No... prawie wszystko ;)
Nie bardzo sie mogłeś zdecydować czy chcesz złączyc tabele i z tego złączenia wybrać dane, czy wyliczyć dane dla każdego towaru bezpośrednio.
Da się na oba sposoby ale nie naraz
NB grupowanie zrobiłeś po nazwie, czyli jak wpiszesz dwa towary o nazwie "Deska", o różnych symbolach to zobaczysz ich mix.
Dwa działające przykłady zrobione na kolanie (reklamacji nie uwzględniam :P)
SELECT
tw__Towar.tw_Nazwa AS [Nazwa towaru],
Stan1 = SUM((CASE WHEN tw_Stan.st_MagId=1 THEN tw_Stan.st_Stan ELSE 0 END)),
Stan2 = SUM((CASE WHEN tw_Stan.st_MagId=2 THEN tw_Stan.st_Stan ELSE 0 END)),
SUM(tw_Stan.st_Stan) AS [ŁĄCZNIE]
FROM
tw_Stan
INNER JOIN tw__Towar ON tw_Stan.st_TowId=tw__Towar.tw_Id
WHERE
tw_Stan.st_MagId IN ('1','2')
AND tw_Stan.st_Stan>0
GROUP BY tw__Towar.tw_Nazwa
SELECT
Nazwa = T.tw_Nazwa,
Stan1 = (SELECT SUM(st_Stan) FROM tw_Stan WHERE st_MagId = 1 AND st_TowId = T.tw_Id),
Stan2 = (SELECT SUM(st_Stan) FROM tw_Stan WHERE st_MagId = 2 AND st_TowId = T.tw_Id),
[Łącznie] = (SELECT SUM(st_Stan) FROM tw_Stan WHERE st_MagId IN (1,2,3) AND st_TowId = T.tw_Id)
FROM
tw__Towar T
-
tomaszf,
dziękuję za odpowiedź - oczywiście wszystko zadziałało :) co do w/w rad - nie skracam póki co nazw tabel żeby lepiej zapamiętać ich nazwy, a apostrofy dodałem z przyzwyczajenia (na tzw. wszelki wypadek gdyby było to pole innego typu).
PS. Czy jest jakiś konkretny powód, dlaczego nie można w tym wypadku skorzystać z FROM w taki sposób jak ja to robiłem? Jeśli funkcja jest w nawiasie to powinna teoretycznie obejmować tylko to co jest w jego obrębie, czyli FROM też.
------
Dzięki candy - fajnie to wszystko ująłeś. Jestem dopiero na początku drogi i ten kod jest wynikiem kilkunastu wcześniejszych prób :D także zupełnie się z tym zgadzam :)
Oczywiście sposoby, które przedstawiłeś są trochę inne niż przez tomaszf - dla mnie super, więcej do analizy :)
-
Czy jest jakiś konkretny powód, dlaczego nie można w tym wypadku skorzystać z FROM w taki sposób jak ja to robiłem? Jeśli funkcja jest w nawiasie to powinna teoretycznie obejmować tylko to co jest w jego obrębie, czyli FROM też.
No jest.
Argumentem dla SUM powinna być nazwa kolumny albo wyrażenie, a Ty napisałeś:SUM((tw_Stan.st_Stan) AS [UR] FROM tw_Stan WHERE tw_Stan.st_MagId=1 )
A zatem argumentem dla SUM jest u Ciebie coś takiego:
(tw_Stan.st_Stan) AS [UR] FROM tw_Stan WHERE tw_Stan.st_MagId=1
Co to jest? Ani nazwa kolumny, ani poprawne wyrażenie.
No i dlatego nie działa.
Jeśli już to trzeba było napisać
[UR] = (SELECT SUM(st_stan) FROM tw_Stan WHERE tw_Stan.st_MagId = 1)
Przy czym to powyższe jest poprawne formalnie, ale niekoniecznie oddaje Twoje intencje ;)
-
Możesz skorzystać z jednego z moich darmowych rozwiązań (Generator zestawienia SQL multistany dla Subiekta GT), aby wygenerować takie zestawienie i zobaczyć jak jest zbudowane.