Dane z 3 tabel

0

Witam mam 3 tabele

Klienci
id | nazwa
3 janek
4 tomek

Produkty
id | nazwa | cena
1 mis 32
2 cos 64

Zakupy

id | id_klient | id_produkt | data | dataokres | cena
1 3 1 2011-05-11 2011-05-01 34
2 3 2 2011-05-14 2011-05-01 64
3 4 2 2011-05-22 2011-05-01 63

Chcę żeby pogrupować dane po id_klient i dataokres i uzyskać następujący wynik produkty oddzielone przecinkiem:

klient | produkty | wartosc | dataokres
janek mis, cos 98 2011-05-01
tomek cos 63 2011-05-01

Jak to zrobić w zapytaniem do SQL Server i w C# Linq 2 SQL

0

z CTE nie jestem za dobry, więc jeśli poszalałem to niech mnie ktoś poprawi :)
to zwraca tylko unikalne nazwy produktów, tzn. jeśli w zakupy jest kilka wpisów dla tego samego id_klient, id_produkt, dataokres, to nazwa produktu wyświetli się raz
jeśli chcesz żeby nazwa była tyle razy ile jest wpisów to użyj tej zakomentowanej części

with t0 (cid, dto, total) as
(
    select client_id, dataokres, sum(price) from zakupy group by client_id, dataokres
),
t1 (cid, dto, zid, pname, x) as
(
    select cid, dto, 0, cast('' as varchar(255)), 0 from t0
    union all
    select t1.cid, t1.dto, z.id, t1.pname || z.name ||',', t1.x+1
    from t1, 
    (
        /*
        select z.id,z.client_id,z.dataokres,p.name from zakupy z 
        inner join produkty p on z.product_id = p.id
        */
        select max(z.id) as id,z.client_id,z.dataokres,p.name from zakupy z 
        inner join produkty p on z.product_id = p.id
        group by client_id,z.dataokres,p.name
        
    ) as z
    where t1.zid < z.id and t1.cid = z.client_id and t1.dto = z.dataokres
)

select k.name, t0.dto, t0.total, t1.pname from t0
inner join (select cid, dto, max(zid) maxzid from t1 group by cid, dto) t1m on t0.cid=t1m.cid and t0.dto=t1m.dto
inner join (select cid, dto, max(x) maxx from t1 group by cid, dto) t1n on t0.cid=t1n.cid and t0.dto=t1n.dto
inner join t1 on t0.cid=t1.cid and t0.dto=t1.dto and t1m.maxzid=t1.zid and t1n.maxx=t1.x
inner join klienci k on t0.cid=k.id

tzn. da się to zrobić prościej używając funkcji rankingujących, ale ja mam pod ręką tylko stare db2 gdzie tego nie ma :/
bez testów to powinno mniej więcej być tak

with t1 (nr, cid, dto, total, pname) as
(
    select  row_number() over (partition by z.client_id, z.dataokres order by ), 
            z.client_id, z.dataokres, sum(z.price) as price, p.name
    from zakupy z
    inner join produkty p on p.id=z.product_id
    group by z.client_id, z.dataokres, z.product_id, p.name
)
t2 (nr, cid, dto, total, pname) as 
(
    select * from t1 where nr = 1
    union all
    select t1.nr, t2.cid, t2.dto, t2.total, t2.pname || ',' || t1.pname
    from t1,t2
    where t2.nr + 1 = t1.nr and t1.cid=t2.cid and t1.dto=t2.dto
)
select k.name, t2.dto, t2.total, t2.pname from t2
inner join (select cid, dto, max(nr) as maxnr from t2 group by cid, dto) as x on x.cid=t2.cid and x.dto=t2.dto and x.maxnr=t2.nr
inner join klienci k on t2.cid=k.id

W sql serverze można jeszcze użyć mechanizmów związanych z xml aby dokonać konkatenacji stringów, ale średnio pamiętam jak, więc z głowy nie chce bzdur pisać. Niemniej używałem tego kilka razy i działało bez zarzutów.
W linq teraz ci nie powiem, bo nie mam jak przetestować.

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