Forum > Software > Czy jest na sali specjalista od baz danych ?

Strona 1 z 1 1
skocz

Inferno

Wysłane 2014-08-05 16:42

Próbuję napisać zapytanie do bazy danych, aby wyliczył mi stan poszczególnych indeksów w magazynie na okres całego roku, z przeskokiem na co miesiąc.
Czyli ma to być mniej więcej tak:

Pozycja | sztuk Styczen | styczen wartosc (aż do grudnia) |  jednostka | magazyn | opis
A         | 299                 | 323,98                                  | kg           | Głowny    | kilo mąki
B         | 32                   | 38,33                                   | szt           | Zapas      | worek mięcha


Cały stan (zakup i sprzedaż) pozycji jest w jednej tabeli, kilka dodatkowych detali są pobierane z innej tabeli.
Kłopot jest w tym, że w jakiś sposób wywala mi błąd, że przekroczono limit 256 tabel. Mogę napisać zapytanie do 3 miesięcy, to jeszcze działa, a jak chcę już 4 - 5 miesięcy, to limit przekroczony. Dodam, że w tabeli jest około 100,000 rekordów, więc wykonanie zapytania do 3 miesięcy trwa około 1 minuty (może taka kiepska optymalizacja, nie wiem).
Nie wiem do końca jak sobie z takim czymś poradzić, próbowałem z dodatkową tabelą, aby w niej zapisać wynik, ale też nie dało to rezultatu.
Moje zapytanie, które jeszcze działa, wygląda tak:
SELECT PLA.ITEMNMBR,  PLA.TRXLOCTN,
isnull((SELECT SUM(TRXQTY) FROM PLIV100 WHERE (PLA.ITEMNMBR = ITEMNMBR) AND (DOCDATE <= '2014-01-31') AND (PLA.TRXLOCTN = TRXLOCTN)),0) AS 'Styczeń ilość', 
isnull((SELECT SUM(EXTDCOST) FROM PLIV100  WHERE (PLA.ITEMNMBR = ITEMNMBR) AND (DOCDATE <= '2014-01-31') AND (PLA.TRXLOCTN = TRXLOCTN)),0) AS 'Styczeń wartość',
isnull((SELECT SUM(TRXQTY) FROM PLIV100 WHERE (PLA.ITEMNMBR = ITEMNMBR) AND (DOCDATE <= '2014-02-28') AND (PLA.TRXLOCTN = TRXLOCTN)),0) AS 'Luty ilość', 
isnull((SELECT SUM(EXTDCOST) FROM PLIV100  WHERE (PLA.ITEMNMBR = ITEMNMBR) AND (DOCDATE <= '2014-02-28') AND (PLA.TRXLOCTN = TRXLOCTN)),0) AS 'Luty wartość',
isnull((SELECT SUM(TRXQTY) FROM PLIV100 WHERE (PLA.ITEMNMBR = ITEMNMBR) AND (DOCDATE <= '2014-03-31') AND (PLA.TRXLOCTN = TRXLOCTN)),0) AS 'Marzec ilość', 
isnull((SELECT SUM(EXTDCOST) FROM PLIV100  WHERE (PLA.ITEMNMBR = ITEMNMBR) AND (DOCDATE <= '2014-03-31') AND (PLA.TRXLOCTN = TRXLOCTN)),0) AS 'Marzec wartość'
FROM PLIV100 PLA
GROUP BY PLA.ITEMNMBR, PLA.TRXLOCTN


Jak sobie z tym poradzić ? Bo mogę wszystko wrzucić do Excela i tam formułą policzyć, ale wtedy Excel z taką dużą ilością danych będzie trochę mielić i potem zapisać będzie trochę trwało.

kowgli

  • kowgli
  • wiadomość Użytkownik

  • 4367 wypowiedzi

Wysłane 2014-08-05 17:18 , Edytowane 2014-08-05 17:21

Próbujesz robić tabelą przestawną, a do tego SQL się słabo nadaje.

Policzyłbym to w dwóch krokach:
1. Najpierw do tabeli tymczasowej, w prostszej postaci (z powtórzeniami)
Pozycja | Miesiac | Sztuk | Wartość | Jednostka | Magazyn | Opis

SELECT 
  PLA.ITEMNMBR As ItemNr, 
  MONTH(DOCDATE) AS Month, 
  SUM(TRXQTY) AS Qty, 
  SUM(EXTDCOST) AS Cost
  PLA.TRXLOCTN AS Location
FROM 
  PLIV100 
GROUP BY 
  PLA.ITEMNMBR, 
  PLA.TRXLOCTN, 
  MONTH(DOCDATE)


Wyjdzie Ci tu dużo mniej niż 100k rekordów i będa już zagregowane

2. Później drugie zapytanie grupując po ItemNr i Location i filtrując po Month w kolejnych podzapytaniach (podobnie jak robileś wczesniej, tego chyba nie da się uniknąć, ale robisz to już na zagregowanych danych).

Ewentualnie możesz podpiąc pierwsze zapytanie do Excela i zrobić w nim tabelą przestawną.

Inferno

Wysłane 2014-08-05 19:12

Trochę nie o to chodzi, ale widzę, że koncepcja w miarę porządna.

O te miesiące chodzi o to, że np. stan magazynu na styczeń, luty, marzec itd. w zależności jaki rok się wybierze 2013, 1014 itd.

W tej chwili on grupuje po dacie dokumentu, więc stan magazynowy nie zgadza się z faktem, przykład:
w tym zapytaniu wyświetli mi pozycję A w miesiącu 1 jak i 6. W miesiącu 1 ilość jest -1, a w miesiącu 6 ilość to 30. Suma się zgadza z ilością, ale to nie o to chodzi.

Mimo to, pomysł jest całkiem fajny, bo ja na siłę próbowałem utworzyć dodatkowe 24 kolumny (po 12 dla ilości i wartości), ale jak mówisz jest to tabela przestawna i może dlatego był z tym problem. Spróbuję zrobić zapytanie, albo w pętli, aby mi utworzyło miesiące w wierszach, tak jak to teraz ma być. Całkiem fajna opcja, bo tabel mniej, ale wierszy znacznie więcej będzie (mimo to chyba w Excelu prostszą formułę da się utworzyć), ewentualnie spróbuję zrobić jedną wielką tabelę z każdym miesiącem osobna i dwanaście razy wykonam operację wstawiania do tabeli i potem po prostu ją wyświetlę. Mniej powinno być wierszy, ale większa tabela no i bardziej specyficzna potem formuła w Exelu.

kowgli

  • kowgli
  • wiadomość Użytkownik

  • 4367 wypowiedzi

Wysłane 2014-08-05 22:51 , Edytowane 2014-08-05 22:51

Z twojego zapytania wnioskowałem, ze masz tam dane jedynie z 2014 roku.
Jeśli dodatkowo po roku chcesz filtrować, to dołóż WHERE YEAR(DOCDATE) = ...
Ewentualnie dołoż kolumnę z rokiem i grupuj.

Wierszy będzie oczywiście sporo - max 12 x ilośc produktów x ilośc lat danych, ale na pewno mniej niż 100.000. Dodatkowo będziesz miał tylko 1 wiersz na każdą kombinację, co powinno bardzo przyspieszyć ostateczne zapytanie. Dodatkowo zamiast SELECT SUM(X) możesz wziąć SELECT TOP (1) X, co powinno też bardzo przyspieszyć, bo nie będzie szukać dalej po znalezieniu pierwszego wystąpienia.

Strona 1 z 1 1
skocz

Kto jest online: 2 użytkowników, 221 gości

nickey , wojtek72 ,