Krótsza alternatywa dla UNION

0

Cześć, jestem kompletnie początkująca w SQL, także proszę o wyrozumiałość :)

Sytuacja jest taka, mam cenniki w bazie osobno dla każdego produktu. Produktów jest 39, co daje 39 osobnych tabel. Mają one taka samą strukturę, różnią się tylko numerem produktu.

I teraz chcę wyciągnąć te cenniki w jednej zgrabnej tabeli. Napisałam kod, który działa, ale jest bardzo długi i męczący w edycji i ogólnie czuję, że ze względu na identyczną strukturę pewnie da się to zrobić lepiej. Czy ktoś z Kolegów/Koleżanek potrafiłby mnie nakierować, jak inaczej sformułować te zapytanie?

Korzystam z dataclipów na Heroku (Postrgresql).

--1
SELECT clients.name, 
       products.full_name, 
       null AS Number_of_floors, 
       gross_floor_area AS Area, 
       null AS Type, 
       null AS Option, 
       null AS Style,  
       price AS Price, 
       rework_price AS Rework_price, 
       null AS Report

FROM client_pricing_product1s
INNER JOIN clients ON client_pricing_product1s.client_id = clients.id
INNER JOIN products ON 'product1' = products.id_name

UNION

--2
SELECT clients.name, 
       products.full_name, 
       null AS Number_of_floors, 
       gross_floor_area AS Area, 
       null AS Type, 
       null AS Option, 
       null AS Style,  
       price AS Price, 
       rework_price AS Rework_price, 
       null AS Report

FROM client_pricing_product2s
INNER JOIN clients ON client_pricing_product2s.client_id = clients.id
INNER JOIN products ON 'product2' = products.id_name

UNION

--3
SELECT clients.name, 
       products.full_name, 
       null AS Number_of_floors, 
       gross_floor_area AS Area, 
       null AS Type, 
       null AS Option, 
       null AS Style,  
       price AS Price, 
       rework_price AS Rework_price, 
       null AS Report

FROM client_pricing_product3s
INNER JOIN clients ON client_pricing_product3s.client_id = clients.id
INNER JOIN products ON 'product3' = products.id_name

UNION

--4
SELECT clients.name, 
       products.full_name, 
       null AS Number_of_floors, 
       gross_floor_area AS Area, 
       null AS Type, 
       null AS Option, 
       null AS Style,  
       price AS Price, 
       rework_price AS Rework_price, 
       null AS Report

FROM client_pricing_product4s
INNER JOIN clients ON client_pricing_product4s.client_id = clients.id
INNER JOIN products ON 'product4' = products.id_name

--itd do 39 :) 
10

Czy ktoś z Kolegów/Koleżanek potrafiłby mnie nakierować, jak inaczej sformułować te zapytanie?

IMO należy po prostu przerobić schemat bazy danych tak, aby istniała wspólna tabela client_pricing_products; wszystko inne będzie hakowaniem nad spaghetti 👀

0
Patryk27 napisał(a):

Czy ktoś z Kolegów/Koleżanek potrafiłby mnie nakierować, jak inaczej sformułować te zapytanie?

IMO należy po prostu przerobić schemat bazy danych tak, aby istniała wspólna tabela client_pricing_products; wszystko inne będzie hakowaniem nad spaghetti 👀

Okej, dziękuję za odpowiedź, niestety nie mam takich uprawnień. Także na razie to odpada, może kiedyś, ale rozumiem, że po prostu nie ma jakiegoś magicznego klucza, którego nie znam, dzięki któremu ten kod wyglądałby trochę lepiej, to też mi wystarczy za odpowiedź :)

2

Nie ma mgaicznego rozwiazania. Mozna sie bawić w jakimś generowaniem kodu i odpalaniem dynamicznym https://www.postgresql.org/docs/current/ecpg-dynamic.html. Czyli robisz funkcje która pobiera numer produktu I na tej podstawie generuje sql z odpowiednią tabelka i zwraca dane. Mozesz tez to przykryć widokiem. Ogólnie ktos kto.to wymyślił to nie ogarną teamtu po ludzku.

0
S4t napisał(a):

Nie ma mgaicznego rozwiazania. Mozna sie bawić w jakimś generowaniem kodu i odpalaniem dynamicznym https://www.postgresql.org/docs/current/ecpg-dynamic.html. Czyli robisz funkcje która pobiera numer produktu I na tej podstawie generuje sql z odpowiednią tabelka i zwraca dane. Mozesz tez to przykryć widokiem. Ogólnie ktos kto.to wymyślił to nie ogarną teamtu po ludzku.

Dziękuję za wskazówkę, poczytam i pokombinuję, może na tu i teraz uda się coś ulepić :)

4

To jakiś działający program, czy po prostu uczysz się SQL na tej bazie?
Jeśli to nie nauka, to zróbcie refaktor póki tych produktów jest tylko 30. Wyobraź sobie sytuację gdy tych produktów jest 3000.
Poczytaj o postaciach normalnych i normalizacji bazy, skoro wszystkie tabele są takie same i tyczą się produktu to powinna być to jedna tabela.

7
Patryk27 napisał(a):

; wszystko inne będzie hakowaniem nad spaghetti 👀

ładnie powiedziane z tym spagetti.
Jak bym porównał do przetrawionego spagetti

Zgadzam się z kolegami.
Projekt bazy JEST PATOLOGICZNY *) i trzeba to pożegnać póki jest mało.

*) excellowiec w roli "nie chcem, ale bendem sqlowcem"

0

Dzięki za wszystkie podpowiedzi, to co napisaliście jest pomocne w ustaleniu priorytetów ;)

1

Wygeneruj sobie jakimś skryptem ten kod zapytań z UNION, wrzuć go do widoku i potem używaj tylko widoku do obsługi produktów.
Po poprawieniu struktury tabel korygujesz tylko widok na SELECT ... FROM CLIENT_PRICING_PRODUCTS i voila!

0

Widok albo jakieś podzapytanie.
Coś typu:

with costam as
(select potrzebne_kolumny, 'product1' as costam2 from client_pricing_product1s union all
 select potrzebne_kolumny, 'product2' from client_pricing_product2s union all
 ....
 select potrzebne_kolumny, 'product39' from client_pricing_product39s
 )

 SELECT clients.name, 
       products.full_name, 
       null AS Number_of_floors, 
       gross_floor_area AS Area, 
       null AS Type, 
       null AS Option, 
       null AS Style,  
       price AS Price, 
       rework_price AS Rework_price, 
       null AS Report

FROM costam
INNER JOIN clients ON costam.client_id = clients.id
INNER JOIN products ON costam.costam2 = products.id_name

Możliwe, że jakieś distinct w ostatnim select (bo masz union nie union all w oryginalnym potworku).

A ogólnie tak, jak pisali przedmówcy. Zabić to jak najszybciej.

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