Paweł Koralewski

Paweł Koralewski architekt aplikacji,
team leader

Temat: [pgsql] wartość pierwszego wiersza z kilku zgrupowanych

Mam towary, faktury i klientów. Na fakturze dla klienta towar ma cenę sprzedaży netto. W raporcie potrzebuję dla każdego klienta dla towaru id=45 mieć najniższą cenę sprzedaży oraz cenę sprzedaży z pierwszego dokumentu.

Proste grupowanie oprócz tego, że nie wiem, jak uzyskać tę pierwszą cenę sprzedaży :( Wiem, że mogę zrobić podzapytanie, ale wolałbym tego uniknąć.

Struktura (uproszczona):

tabela clients
-clent_id serial

tabela products
-product_id serial
-name text

tabela invoices
-invoice_id serial
-client_id int

tabela invoices_rows
-invoice_row_id serial
-invoice_id int
-product_id int
-price double precisionPaweł Koralewski edytował(a) ten post dnia 24.03.12 o godzinie 12:28

konto usunięte

Temat: [pgsql] wartość pierwszego wiersza z kilku zgrupowanych

denormalizacja
dodajesz kolumny do tabeli z towarami jedna do najniższej ceny sprzedaży, drugą do sprzedaży z pierwszego dokumentu

później robisz update tych wartości jakimś zapytaniem

a w aplikacji przy kolejnych wpisach dodajesz dwa updat-y w transakcji na końcu procesu sprzedaży,

update towar set  `sprzedaży z pierwszego dokumentu` = cena when `sprzedaży z pierwszego dokumentu` is null and id = 45

update towar set ` najniższą cenę sprzedaży ` = cena when ` najniższą cenę sprzedaży ` > cena and id = 45


joiny przy tego typu mykaczu wymiękają
Paweł Koralewski

Paweł Koralewski architekt aplikacji,
team leader

Temat: [pgsql] wartość pierwszego wiersza z kilku zgrupowanych

Przemysław R.:
denormalizacja
dodajesz kolumny do tabeli z towarami jedna do najniższej ceny sprzedaży, drugą do sprzedaży z pierwszego dokumentu

To ma być dla każdego klienta, więc nie mogę dodać kolumny do tabeli z towarami.

Przedstawiona struktura jest nierzeczywista, tylko na potrzeby rozwiązania problemu uzyskania wartości pierwszego wiersza z kilku zgrupowanych. W mojej rzeczywistej sytuacji odpowiednik tabeli invoices_rows ma 65mln rekordów, faktur jest 4400 a klientów 1300.

konto usunięte

Temat: [pgsql] wartość pierwszego wiersza z kilku zgrupowanych

hmm dodaj tabelkę zawierającą idklienta, idTowaru i te dwie kolumny, jeden join i pozamiatane
Przemysław Kantyka

Przemysław Kantyka Oracle Certified
Professional, Oracle
Database SQL
Certif...

Temat: [pgsql] wartość pierwszego wiersza z kilku zgrupowanych


create table clients (client_id serial);

create table products (product_id serial, name text);

create table invoices (invoice_id serial, client_id int);

create table invoices_rows(invoice_row_id serial, invoice_id int, product_id int, price double precision);

insert into clients values (1);

insert into clients values (2);

insert into products values (1, 'Produkt A');

insert into products values (2, 'Produkt B');

insert into products values (3, 'Produkt C');

insert into invoices values (100, 1);

insert into invoices values (200, 2);

insert into invoices_rows values (1000, 100, 1, 100);

insert into invoices_rows values (1001, 100, 2, 101);

insert into invoices_rows values (1002, 100, 3, 103);


insert into invoices_rows values (1003, 200, 1, 103);

insert into invoices_rows values (1004, 200, 2, 102);

insert into invoices_rows values (1005, 200, 3, 101);

insert into invoices_rows values (1006, 200, 3, 102);

select invoice_id, client_id, min(price), min(pierwsza_cena) as pierwsza_cena from (
select i.invoice_id, client_id, price, first_value(price) over (partition by client_id order by i.invoice_id) as pierwsza_cena
from invoices i, invoices_rows r
where i.invoice_id = r.invoice_id and product_id = 3
) as q group by invoice_id, client_id;


Pozdrawiam
Paweł Koralewski

Paweł Koralewski architekt aplikacji,
team leader

Temat: [pgsql] wartość pierwszego wiersza z kilku zgrupowanych

Przemysław Kantyka:

select invoice_id, client_id, min(price), min(pierwsza_cena) as pierwsza_cena from (
select i.invoice_id, client_id, price, first_value(price) over (partition by client_id order by i.invoice_id) as pierwsza_cena
from invoices i, invoices_rows r
where i.invoice_id = r.invoice_id and product_id = 3
) as q group by invoice_id, client_id;

Dzięki za odpowiedź.

No właśnie, na stackoverflow mi zasugerowano funkcje operujące na oknach (over/partition). Ewentualnie CTE albo jednal subselect jako całkiem wydajne.

konto usunięte

Temat: [pgsql] wartość pierwszego wiersza z kilku zgrupowanych

wydajne dla jakiej ilości danych?
Przemysław Kantyka

Przemysław Kantyka Oracle Certified
Professional, Oracle
Database SQL
Certif...

Temat: [pgsql] wartość pierwszego wiersza z kilku zgrupowanych

Wpis na blogu na temat pierwszego, drugiego i n-tego rekordu pokazuje tez alternatywną metodę osiągnięcia wyniku: http://blog.dataconsulting.pl/2012/03/pierwszy-drugi-n...

konto usunięte

Temat: [pgsql] wartość pierwszego wiersza z kilku zgrupowanych

Przemysław Kantyka:
Wpis na blogu na temat pierwszego, drugiego i n-tego rekordu pokazuje tez alternatywną metodę osiągnięcia wyniku: http://blog.dataconsulting.pl/2012/03/pierwszy-drugi-n...

a jak wygląda sprawa wydajności przy dużych ilościach danych w pojedynczym zapytaniu?

Następna dyskusja:

Jedno zapytanie do kilku ta...




Wyślij zaproszenie do