Sumarizace dvou tabulek

C++, C#, Visual Basic, Delphi, Perl a ostatní

Moderátor: Moderátoři Živě.cz

Odeslat příspěvekod LadyWinnie 18. 10. 2017 14:37

Ahoj,
mám takový menší problém seskládat dohromady Query pro sumarizaci množství dvou tabulek kde mají společné ID druhu zboží. Tabulky vypadají následovně (napíši pouze důležité sloupce bez klasického id, createDate, UpdateDate a pod.):

1) Název: Privezeno
ID_DruhZbozi
Mnozstvi

2) Název: Odvezeno
ID_DruhZbozi
Mnozstvi

*3) Název: DruhZbozi
ID
Nazev
Jednotka

Potřebuji něco jako SUM(P.Mnozstvi) - SUM(O.Mnozstvi) s GROUP BY ID_DruhZbozi.
Nejlíp kdybyste mi to napsali i s LEFT JOIN na DruhZbozi abych mohla vzít i název a jednotku z třetí tabulky, proto jsem ji tam dopsala. :) Lze to zapsat do jedné Query? Já myslím že by to snad nějak mělo jít ale pořád se mi nedaří to sloučit se sumarizací druhé tabulky.. :( Pokud by se vám to podařilo byla bych vám moc vděčná. Pokud ne tak to hold udělám na dva selecty a podle druhu budu odečítat foreachem.. :( ale toho se chci vyvarovat :D
LadyWinnie
Kolemjdoucí
Uživatelský avatar

Odeslat příspěvekod Ertefol 18. 10. 2017 23:11

U SQL se mně osobně osvědčilo jít vždy "odzadu". Tedy pokud chci přidat třetí tabulku, musím si udělat nejdříve jeden join, a pak až případně uzávorkovat na třetí.

Kód: Vybrat vše
SELECT Privezeno.ID_DruhZbozi, Privezeno.Mnozstvi - Odvezeno.Mnozstvi as Rozdil
FROM Privezeno
LEFT JOIN Odvezeno ON Privezeno.ID_DruhZbozi = Odvezeno.ID_DruhZbozi
GROUP BY Privezeno.ID_DruhZbozi


Při přidání třetí tabulky pak tedy něco ve smyslu
Kód: Vybrat vše
SELECT DruhZbozi.ID, DruhZbozi.Nazev, p.rozdil, DruhZbozi.Jednotka
FROM (SELECT Privezeno.ID_DruhZbozi, Privezeno.Mnozstvi - Odvezeno.Mnozstvi as Rozdil
FROM Privezeno LEFT JOIN Odvezeno ON Privezeno.ID_DruhZbozi = Odvezeno.ID_DruhZbozi
GROUP BY Privezeno.ID_DruhZbozi)p RIGHT JOIN DruhZbozi on p.ID_DruhZbozi = DruhZbozi.ID
PC, Wii U, 3DS
"Slabé pohlaví je silnějším pohlavím z důvodu slabosti silnějšího pohlaví k slabšímu pohlaví." - Přísloví
Jakub Kovář, externí redaktor Games, LEVELu, Pevnosti
Ertefol
Junior
Uživatelský avatar

Odeslat příspěvekod LadyWinnie 19. 10. 2017 07:31

Query poskládaná dle předlohy mi prošla v pořádku, ale nejsem si jistá zda počítá správné hodnoty. Porovnávala jsem je s hodnotama, který počítám z již zmíněného foreache, který se snažím vypustit a zrychlit tak chod programu, ale neshodují se... Hodnoty z jedné sumarizace mi mnohdy vychází i záporné přestože program nedovoluje odvézt něco co tam není :D ... ale třeba to tak opravdu je díky zkušebním datům, který jsem zpočátku mohla zapsat odvoz bez omezení, ale není to moc pravděpodobné.. přesto si myslím že by se měly obě varianty shodovat. Query vypadá následovně.. je správně? (RIGHT JOIN mi vyhazoval chybu tak jsem jej nahradila LEFT JOIN) :oboze

Kód: Vybrat vše
SELECT
             S.SumMnozstvi 'SumMnozstvi',
             DZ.Id 'DruhZboziId',
             DZ.Nazev 'DruhZboziNazev',
             DZ.Jednotka 'DruhZboziJednotka'
                                                                                                                                           
             FROM (SELECT P.ID_DruhZbozi,
                    P.Mnozstvi - O.Mnozstvi AS SumMnozstvi
             FROM Prijem AS P
             LEFT JOIN OdvozZbozi AS O
                    ON O.ID_DruhZbozi = P.ID_DruhZbozi
             GROUP BY P.Id_DruhZbozi)S

             LEFT JOIN DruhZbozi AS DZ
                     ON S.ID_DruhZbozi = DZ.Id
             ORDER BY DZ.Nazev
LadyWinnie
Kolemjdoucí
Uživatelský avatar

Odeslat příspěvekod Ertefol 19. 10. 2017 07:55

Left Join v tomto případě dobře není, neukáže vám zboží bez pohybu... Tím pádem bych použil normální JOIN, vyjde nastejno, jako Left Join.

Jinak zadání mně přišlo lehce zvláštní, protože neříkáte, jestli počítáte data od začátku věků nebo máte někde tabulku s výchozím skladovým stavem... Odvézt tak můžete zboží, které bylo např. na začátku roku skladem, nebo se zbavujete starých zásob - tam bude mínus.

Jinak by ale query měla počítat správně...
PC, Wii U, 3DS
"Slabé pohlaví je silnějším pohlavím z důvodu slabosti silnějšího pohlaví k slabšímu pohlaví." - Přísloví
Jakub Kovář, externí redaktor Games, LEVELu, Pevnosti
Ertefol
Junior
Uživatelský avatar

Odeslat příspěvekod LadyWinnie 19. 10. 2017 11:41

Zkoušela jsem jednotlivé sumarizace rozdělit a podívat se které dvě hodnoty vlastně odečítá a nevím proč ale Sumarizace se mi nějak zvláštně násobí(například z 38 odvezu 2 ale přitom mi to spočítá 38 - 4) snad nějak podle nalezených řádků či čo. To je důvod, proč se mi zobrazily jiné hodnoty než jsem očekávala a mnohdy i záporné. Query zůstala víceméně stejná... Čím to je způsobené? :D :D někdy mám pocit že si ze mě jen počítač střílí a má vtipnou náladu :D

výchozí skladový stav nemám.. z této query se snažím počítat aktuální stav skladu podle toho kolik toho přivezli a kolik jakoby vydali v určitém období.. (časové rozmezí doplním do query až v závěru.. to už je jednoduché :) )
LadyWinnie
Kolemjdoucí
Uživatelský avatar

Odeslat příspěvekod LadyWinnie 19. 10. 2017 12:55

Konečně se mi to podařilo napsat tak aby to fungovalo jak potřebuji :)

Kód: Vybrat vše
SELECT
   P.ID_DruhZbozi 'PrijemID_DruhZbozi',
   SUM(P.Mnozstvi) 'SumPrijemMnozstvi',
   DZ.Id 'DruhZboziId',
   DZ.Nazev 'DruhZboziNazev',
   DZ.Jednotka 'DruhZboziJednotka',
   (SELECT SUM(Mnozstvi)
        FROM OdvozZbozi
        WHERE ID_DruhZbozi = P.ID_DruhZbozi) AS 'SumOdvozMnozstvi'                                                                   
   FROM Prijem AS P
   JOIN DruhZbozi AS DZ
            ON P.ID_DruhZbozi = DZ.Id 
   GROUP BY P.ID_DruhZbozi                                             
   ORDER BY DZ.Nazev


Následně při vkládání sloupců do proměnných odečtu odvoz z prijmu

Kód: Vybrat vše
private Sumarizace(SQLiteDataReader row)
        {
            ID_DruhZbozi = string.IsNullOrEmpty(row["DruhZboziId"].ToString()) ? Guid.Empty : (Guid)row["DruhZboziId"];
            MnozstviPrivoz = string.IsNullOrEmpty(row["SumPrijemMnozstvi"].ToString()) ? 0 : Math.Round((double)row["SumPrijemMnozstvi"], 1);
            MnozstviOdvoz = string.IsNullOrEmpty(row["SumOdvozMnozstvi"].ToString()) ? 0 : Math.Round((double)row["SumOdvozMnozstvi"], 1);
            jednotka = (string.IsNullOrEmpty(row["DruhZboziJednotka"].ToString()) ? string.Empty : (string)row["DruhZboziJednotka"]);
            STMnozstvi = Convert.ToString(MnozstviPrivoz - MnozstviOdvoz) + " " + jednotka;
            NazevZbozi = string.IsNullOrEmpty(row["DruhZboziNazev"].ToString()) ? string.Empty : (string)row["DruhZboziNazev"];
        }


Děkuji za trpělivost a užitečnou radu :)
LadyWinnie
Kolemjdoucí
Uživatelský avatar

Odeslat příspěvekod JanFiala 19. 10. 2017 18:59

Udělej 2 samostatne selecty spojene pres UNION ALL a nakonec pridej nazev
Kód: Vybrat vše
select b.ID, j.Nazev, Mnozstvi = Sum(b.MNozstvi),
  from (
    Select a.ID, a.Mnozstvi
      from privezeno a
    union all
    select a.ID, -a.Mnozstvi
      from odvezeno a
  ) b
  join Jednotka j on b.ID = j.ID
  group by b.ID, j.Nazev
  order by j.ID
Co můžeš udělat dnes, odlož na včerejšek
JanFiala
Expert
Uživatelský avatar


Kdo je online

Uživatelé procházející toto fórum: Žádní registrovaní uživatelé a 0 návštevníků