ďťż
 
[SQL] Agregacja danych hierarchicznych ďťż
 
[SQL] Agregacja danych hierarchicznych
Zobacz wiadomości
 
Cytat
A gdyby tak się wedrzeć na umysłów górę, / Gdyby stanąć na ludzkich myśli piramidzie, / I przebić czołem przesądów chmurę, / I być najwyższą myślą wcieloną. . . Juliusz Słowacki, Kordian
Indeks BCB i MySQL subiekt gt fototapeta
 
  Witamy

[SQL] Agregacja danych hierarchicznych



Tomasz Wrzodak - 27-04-2006 00:17
[SQL] Agregacja danych hierarchicznych
  Witam,
Zupełnie nie mam pomysłu, jak uzyskać wynik postaci:

id nazwa wartosc
==============================
1 1 310
2 1.1 70
4 1.1.2 60
RAZEM 310

z danych z tabeli postaci:

id nazwa wartosc rodzic
=======================================
1 1
2 1.1 1
3 1.1.1 10 2
4 1.1.2 20 2
5 1.1.2.1 40 4
6 1.2 80 1
7 1.3 160 1

W tej tabeli pole rodzic jest kluczem obcym do pola id tej samej
tabeli, czyli struktura jest hierarchiczna.
W wyniku chcę otrzymać wszystkie rekordy z tabeli, które są
rodzicami na jakimkolwiek poziomie hierarchii (w rzeczywistości tych
poziomów jest 5), wraz z sumą pola wartość wszystkich potomków
tych rekordów plus wartość pola "wartość" samego rekordu
będącego rodzicem (jeśli taką posiada). Np. w powyższych danych
chodzi o przypadek rekordu o id=4, który zarówno ma potomków, jak i
sam ma wartość <> null, więc w wyniku wartość dla niego=jego
wartość + suma wartości potomków.

Siedzę nad tym już drugi dzień, może ktoś może coś
podpowiedzieć?





Krzysztof Naworyta - 27-04-2006 00:17

  Tomasz Wrzodak <twrzodak@gmail.com> napisał:

| Zupełnie nie mam pomysłu, jak uzyskać wynik postaci:
|
| id nazwa wartosc
| ==============================
| 1 1 310
| 2 1.1 70
| 4 1.1.2 60
| RAZEM 310
|
|
| z danych z tabeli postaci:
|
| id nazwa wartosc rodzic
| =======================================
| 1 1
| 2 1.1 1
| 3 1.1.1 10 2
| 4 1.1.2 20 2
| 5 1.1.2.1 40 4
| 6 1.2 80 1
| 7 1.3 160 1
|
| W tej tabeli pole rodzic jest kluczem obcym do pola id tej samej
| tabeli, czyli struktura jest hierarchiczna.
| W wyniku chcę otrzymać wszystkie rekordy z tabeli, które są
| rodzicami na jakimkolwiek poziomie hierarchii (w rzeczywistości tych
| poziomów jest 5), wraz z sumą pola wartość wszystkich potomków
| tych rekordów plus wartość pola "wartość" samego rekordu
| będącego rodzicem (jeśli taką posiada). Np. w powyższych danych
| chodzi o przypadek rekordu o id=4, który zarówno ma potomków, jak i
| sam ma wartość <> null, więc w wyniku wartość dla niego=jego
| wartość + suma wartości potomków.

SELECT
Z1.id
, Z1.nazwa
,
nz(Sum(Z1.wartosc))+nz(Sum(Z2.wartosc))+Nz(Sum(Z3. wartosc))+Nz(Sum(Z4.wartosc))
AS razem
FROM
((
Tabela1 AS Z1
LEFT JOIN
Tabela1 AS Z2
ON
Z1.ID = Z2.rodzic
)
LEFT JOIN
Tabela1 AS Z3
ON
Z2.ID = Z3.rodzic
)
LEFT JOIN
Tabela1 AS Z4
ON
Z3.ID = Z4.rodzic
WHERE
Exists (select * From Tabela1 x where x.rodzic=z1.id)
GROUP BY
Z1.ID, Z1.nazwa

--
KN
(MVP MS Office Access)

archiwum grupy:
http://groups.google.pl/advanced_gro...up=pl*msaccess




=?ISO-8859-2?Q?Pawe=B3_Matejski?= - 27-04-2006 00:17

  Tomasz Wrzodak napisał(a):
> Witam,
> Zupełnie nie mam pomysłu, jak uzyskać wynik postaci:
>
> id nazwa wartosc
> ==============================
> 1 1 310
> 2 1.1 70
> 4 1.1.2 60
> RAZEM 310
>
>
> z danych z tabeli postaci:
>
> id nazwa wartosc rodzic
> =======================================
> 1 1
> 2 1.1 1
> 3 1.1.1 10 2
> 4 1.1.2 20 2
> 5 1.1.2.1 40 4
> 6 1.2 80 1
> 7 1.3 160 1
>
> W tej tabeli pole rodzic jest kluczem obcym do pola id tej samej
> tabeli, czyli struktura jest hierarchiczna.
> W wyniku chcę otrzymać wszystkie rekordy z tabeli, które są
> rodzicami na jakimkolwiek poziomie hierarchii (w rzeczywistości tych
> poziomów jest 5), wraz z sumą pola wartość wszystkich potomków
> tych rekordów plus wartość pola "wartość" samego rekordu
> będącego rodzicem (jeśli taką posiada). Np. w powyższych danych
> chodzi o przypadek rekordu o id=4, który zarówno ma potomków, jak i
> sam ma wartość <> null, więc w wyniku wartość dla niego=jego
> wartość + suma wartości potomków.
>
> Siedzę nad tym już drugi dzień, może ktoś może coś
> podpowiedzieć?

Czytaj FAQ grupy bazy-danych. Tam pisze, że trzeba podać baze w jakiej
to robisz, bo w jednej da sie to zrobic tak, w innej inaczej.
Pozatym pisze tam również, jak radzić sobie ze strukturami drzewiastymi.

--
P.M.




=?ISO-8859-2?Q?Micha=B3?= Kuratczyk - 27-04-2006 00:17

  Tomasz Wrzodak wrote:
> Zupełnie nie mam pomysłu, jak uzyskać wynik postaci:
>
> id nazwa wartosc
> ==============================
> 1 1 310
> 2 1.1 70
> 4 1.1.2 60
> RAZEM 310
>
>
> z danych z tabeli postaci:
>
> id nazwa wartosc rodzic
> =======================================
> 1 1
> 2 1.1 1
> 3 1.1.1 10 2
> 4 1.1.2 20 2
> 5 1.1.2.1 40 4
> 6 1.2 80 1
> 7 1.3 160 1

Oczywiście nie napisałeś jaka baza i nie podałeś gotowych CREATE i INSERT,
albo proszę - wersja dla Oracle 10g:

SQL> select * from drzewko;

ID NAZWA WARTOSC RODZIC
---------- ------------------------ ---------- ----------
1 1
2 1.1 1
3 1.1.1 10 2
4 1.1.2 20 2
5 1.1.2.1 40 4
6 1.2 80 1
7 1.3 160 1

7 rows selected.

SQL> select id, nazwa,
2 (select sum(wartosc) from drzewko d2
3 start with d2.id=d.id connect by prior id=rodzic) wartosc
4 from drzewko d
5 where CONNECT_BY_ISLEAF=0
6 start with rodzic is null
7 connect by prior id=rodzic;

ID NAZWA WARTOSC
---------- ------------------------ ----------
1 1 310
2 1.1 70
4 1.1.2 60

--
Michał Kuratczyk





Tomasz Wrzodak - 27-04-2006 00:17

  Wielkie dzieki za odpowiedzi, faktycznie nie przejrzalem FAQ, mea
culpa.
Jesli chodzi o baze danych, to specjalnie nie podalem, bo jest mi
obojetna. Dane mam w Accesie, ale nie ma problemu, by je przetworzyc
np. na Oracle'u czy MS SQLu. Nie chcialem ograniczac liczby
odpowiedzi (fakt - moglem jawnie to napisac).




Tomasz Wrzodak - 27-04-2006 00:17

  Wielkie dzieki za odpowiedzi, faktycznie nie przejrzalem FAQ, mea
culpa.
Jesli chodzi o baze danych, to specjalnie nie podalem, bo jest mi
obojetna. Dane mam w Accesie, ale nie ma problemu, by je przetworzyc
np. na Oracle'u czy MS SQLu. Nie chcialem ograniczac liczby odpowiedzi
(fakt - moglem jawnie to napisac).




Krzysztof Naworyta - 27-04-2006 00:17

 
ups, nie zwróciłem uwagi, że cross-post ...

oczywiście moje rozwiązanie dotyczy access'a i tylko pod warunkiem, że
poziomów jest skończona i z góry określona ilość.

--
KN
(MVP, M$ Office Access)

| Tomasz Wrzodak <twrzodak@gmail.com> napisał:
|
|| Zupełnie nie mam pomysłu, jak uzyskać wynik postaci:

(...)
| SELECT
| Z1.id
| , Z1.nazwa
| ,
|
nz(Sum(Z1.wartosc))+nz(Sum(Z2.wartosc))+Nz(Sum(Z3. wartosc))+Nz(Sum(Z4.wartosc))
| AS razem
| FROM
| ((
| Tabela1 AS Z1
| LEFT JOIN
| Tabela1 AS Z2
| ON
| Z1.ID = Z2.rodzic
| )
| LEFT JOIN
| Tabela1 AS Z3
(...)




Grzegorz Szyszlo - 28-04-2006 00:51

  Tomasz Wrzodak wrote:
> Wielkie dzieki za odpowiedzi, faktycznie nie przejrzalem FAQ, mea
> culpa.
> Jesli chodzi o baze danych, to specjalnie nie podalem, bo jest mi
> obojetna. Dane mam w Accesie, ale nie ma problemu, by je przetworzyc
> np. na Oracle'u czy MS SQLu. Nie chcialem ograniczac liczby
> odpowiedzi (fakt - moglem jawnie to napisac).

przeczytaj FAQ. Tam jest opisane w jaki sposob skonstruowac
struktury drzewiaste. Zrob sobie tabele pomocnicza
z 3ma kolumnami, i wtedy wszelkie sumowania po drzewie
beda znacznie prostsze. jeden join, jeden group.
rozwiazanie jest niezalezne od bazy danych.

znik.




Tomasz Wrzodak - 29-04-2006 00:14

  Witam ponownie,
Po przejzeniu wyników obu powyzszych zapytan (z CONNECT BY dla
Oracle'a i ze zlaczeniami) zauwazylem drobne róznice w wynikach.
Nie wiem, co jest przyczyna, moze ktos podpowie, z ciekawosci
próbuje to rozgryzc...

Róznice pokaze na fragmencie moich danych (wszystko skladnia
Oracle'a):

CREATE TABLE "TWRZODAK"."TMP"(
"ID" NUMBER(10,0),
"ZAKLADKA_ARKUSZA" VARCHAR2(765 BYTE),
"RODZAJ_PROCESOW" VARCHAR2(765 BYTE),
"NUMER_PROCESU" VARCHAR2(765 BYTE),
"NAZWA_PROCESU" VARCHAR2(765 BYTE),
"LICZBA_ETATOW" NUMBER(28,6),
"MIESIECZNA_LICZBA_TRANSAKCJI" NUMBER(28,6),
"RODZIC" NUMBER(10,0)
) ;

-- INSERTING into TMP
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values ('212','ZAKLADKA1','rodzaj1','1.1','1.1','0.10625' ,'230','211');
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values ('213','ZAKLADKA1','rodzaj1','1.1.1','1.1.1',null, null,'212');
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values
('214','ZAKLADKA1','rodzaj1','1.1.1.1','1.1.1.1',' 7.412291','5407.2','213');
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values ('215','ZAKLADKA1','rodzaj1','1.1.2','1.1.2',null, null,'212');
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values
('216','ZAKLADKA1','rodzaj1','1.1.2.1','1.1.2.1',' 4.171148','1089','215');
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values
('217','ZAKLADKA1','rodzaj1','1.1.2.2','1.1.2.2',' 4.657054','2313','215');
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values ('218','ZAKLADKA1','rodzaj1','1.1.3','1.1.3',null, null,'212');
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values
('219','ZAKLADKA1','rodzaj1','1.1.3.1','1.1.3.1',' 5.650897','4292.2','218');
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values
('220','ZAKLADKA1','rodzaj1','1.1.3.2','1.1.3.2',' 1.843772','2633.84','218');
Insert into TMP
("ID","ZAKLADKA_ARKUSZA","RODZAJ_PROCESOW","NUMER_ PROCESU","NAZWA_PROCESU","LICZBA_ETATOW","MIESIECZ NA_LICZBA_TRANSAKCJI","RODZIC")
values
('221','ZAKLADKA1','rodzaj1','1.1.3.3','1.1.3.3',' 0.188641','540','218');

Zapytanie (1) w wersji z CONNECT BY:
with vs as (
select id, zakladka_arkusza, rodzaj_procesow, numer_procesu,
nazwa_procesu,
(select sum(liczba_etatow) from tmp v2 start with v2.id=v.id connect by
prior id=rodzic) liczba_etatow,
(select sum(miesieczna_liczba_transakcji) from tmp v3 start with
v3.id=v.id connect by prior id=rodzic) miesieczna_liczba_transakcji
from tmp v
where CONNECT_BY_ISLEAF=0
start with rodzic=211
connect by prior id=rodzic
)
select numer_procesu,nazwa_procesu,round(vs.liczba_etatow ,2) as le,
round(vs.miesieczna_liczba_transakcji,2) as lt
from vs
order by numer_procesu, nazwa_procesu

Zapytanie (2) w wersji ze zlaczeniami:
with vs as (
SELECT Z1.id, Z1.zakladka_arkusza, Z1.rodzaj_procesow,
Z1.numer_procesu, Z1.nazwa_procesu,
nvl(Sum(Z1.liczba_etatow),0)+nvl(Sum(Z2.liczba_eta tow),0)+nvl(Sum(Z3.liczba_etatow),0)
+nvl(Sum(Z4.liczba_etatow),0)+nvl(Sum(Z5.liczba_et atow),0) AS
liczba_etatow,
nvl(Sum(Z1.miesieczna_liczba_transakcji),0)+nvl(Su m(Z2.miesieczna_liczba_transakcji),0)
+nvl(Sum(Z3.miesieczna_liczba_transakcji),0)+nvl(S um(Z4.miesieczna_liczba_transakcji),0)
+nvl(Sum(Z5.miesieczna_liczba_transakcji),0) AS
miesieczna_liczba_transakcji
FROM tmp Z1
LEFT JOIN tmp Z2 ON Z1.ID=Z2.rodzic
LEFT JOIN tmp Z3 ON Z2.ID=Z3.rodzic
LEFT JOIN tmp Z4 ON Z3.ID=Z4.rodzic
LEFT JOIN tmp Z5 ON Z4.ID=Z5.rodzic
WHERE Exists (select * From tmp x where x.rodzic=z1.id)
GROUP BY Z1.ID, Z1.numer_procesu, Z1.nazwa_procesu,
Z1.zakladka_arkusza, Z1.rodzaj_procesow
)
select numer_procesu,nazwa_procesu,round(vs.liczba_etatow ,2) as
liczba_etatow, round(vs.miesieczna_liczba_transakcji,2) as
liczba_transakcji
from vs
order by numer_procesu, nazwa_procesu

Wyniki zapytania (1):
"NUMER_PROCESU" "NAZWA_PROCESU" "Liczba_Etatów" "Liczba_Transakcji"
"1.1" "1.1" "24.03" "16505.24"
"1.1.1" "1.1.1" "7.41" "5407.2"
"1.1.2" "1.1.2" "8.83" "3402"
"1.1.3" "1.1.3" "7.68" "7466.04"

Wyniki zapytania (2):
"NUMER_PROCESU" "NAZWA_PROCESU" "L_ETATOW" "L_TRANSAKCJI"
"1.1" "1.1" "24.56" "17655.24"
"1.1.1" "1.1.1" "7.41" "5407.2"
"1.1.2" "1.1.2" "8.83" "3402"
"1.1.3" "1.1.3" "7.68" "7466.04"

Zapytanie (1) zwraca poprawne wyniki. Co jest przyczyna, ze (2), dla
NUMER_PROCESU=
"1.1" zwraca wieksza sume?

Pozdrawiam
Tomasz Wrzodak
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • effulla.pev.pl
  • comp
    jak to =?ISO-8859-2?Q?zrobi=E6=2E=2E=2E=3F_TSQL_sql_server?==?ISO-8859-2?Q?_?= Jak =?windows-1250?Q?pobra=E6_szacowan=B9_wielko=9C=E6_zbiory_wy nikowego_w_MS?==?windows-1250?Q?_SQL_2005=3F?= =?iso-8859-2?Q?=5BMS_SQL=5D_Czy_mo=BFna_wywo=B3a=E6_funkcje_t ylko_raz_dla?==?iso-8859-2?Q?_ca=B3ego_zbioru_=BCr=F3d=B3owego=3F?= [MSSQL] =?ISO-8859-2?Q?zgodno=B6ci_z_licencjami_Microsoft_?==?ISO-8859-2?Q?SQL_Server?= =?ISO-8859-2?Q?k=B3opot_z_uruchomieniem_MY_SQL_dla_C?==?ISO-8859-2?Q?MS_i_CRM_na_Fedora_Core_3?= Oracle PL/SQL Wstawianie =?ISO-8859-2?Q?wynik=F3w_kolekcji_d?==?ISO-8859-2?Q?o_tabeli?= [MSSQL] ACCESS - SQL =?ISO-8859-2?Q?B=B3ad_w_konwersji_lic?==?ISO-8859-2?Q?zb?= =?iso-8859-2?Q?=5Bmssql=5D_Zapytania_rekurencyjne__-_czy_sk=B3adnia_sql?==?iso-8859-2?Q?_co=B6_takiego_przewiduje_=3F?= [Oracle PL/SQL] Cursor i zapis =?ISO-8859-2?Q?rekord=F3w_do_?==?ISO-8859-2?Q?kolejnych_plik=F3w?= =?iso-8859-2?Q?=5BMySQL=5D_Co_minimalnie_potrzebne_zeby_mie=E 6_klienta_My?==?iso-8859-2?Q?SQL_na_Linuxie=3F?=
  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • oefg.opx.pl
  • Cytat

    Decede mihi sole - nie zasłaniaj mi słonca.
    Gdy kogoś kochasz, jesteś jak stworzyciel świata - na cokolwiek spojrzysz, nabiera to kształtu, wypełnia się barwą, światłem. Powietrze przytula się do ciebie, choćby był mróz, a ty masz w sobie tyle radości, że musisz ją rozdawać wokoło, bo się w tobie nie mieści
    Hoc fac - tak czyń.
    A tergo - od tyłu; z tyłu.
    I czarne włosy posiwieją. Safona

    Valid HTML 4.01 Transitional

    Free website template provided by freeweblooks.com