2016-12-02 3 views
1

Ich habe eine Tabelle von Produkten und Preisen. Es enthält 10 verschiedene Preisspalten. Ich bin in der Lage, den niedrigsten Wert aller 10 Preisspalten erfolgreich zu finden.Wie zeige ich den Namen der Spalte an, aus der SQL einen MIN-Wert gefunden hat?

Also, aus diesen Daten:

Prod. Name | Week1 | Week2 | Week N | Week 10 
Pizza  | $1.29 | $1.29 | $1.42 | $1.01 

Und ich anzeigen kann:

Prod. Name | Lowest Price 
Pizza  | $1.01 

Aber wie kann ich hinzufügen, auch eine andere Spalte die Spalte anzuzeigen/s, von denen der niedrigste Wert kam?

Ideal Ausgabe würde wie folgt aussehen:

Prod. Name | Lowest Price | From Week 
Pizza  | $1.01  | 10 

Die Suchabfrage Ich bin mit der Ausgabe angezeigt wird:

SELECT ProdName, LEAST(d1, d2, d3, d4, d5, d6, d7, d8, d9, d10) FROM results;

Edit: Ich vergaß zu erwähnen, dass Ich arbeite mit insgesamt rund 1600 Datenzeilen. Dies macht sicherlich die Codierung ein bisschen komplexer!

Antwort

0

Sie können nicht nur einfache Werte zu vergleichen, sondern auch Datensätze:

with t(x,y,z) as (values(1,3,2),(5,2,3)) 
select *, least((x,'x'::text),(y,'y'::text),(z,'z'::text)) from t; 
 
╔═══╤═══╤═══╤═══════╗ 
║ x │ y │ z │ least ║ 
╠═══╪═══╪═══╪═══════╣ 
║ 1 │ 3 │ 2 │ (1,x) ║ 
║ 5 │ 2 │ 3 │ (2,y) ║ 
╚═══╧═══╧═══╧═══════╝ 

Wenn es nicht genug ist, dann könnte man es jsonb zum Beispiel konvertieren und die Werte in den einzelnen Reihen retrive:

with t(x,y,z) as (values(1,3,2),(5,2,3)) 
select *, j->>'f1' as val, j->>'f2' as fld 
from t, to_jsonb(least((x,'x'::text),(y,'y'::text),(z,'z'::text))) as j; 
 
╔═══╤═══╤═══╤══════════════════════╤═════╤═════╗ 
║ x │ y │ z │   j   │ val │ fld ║ 
╠═══╪═══╪═══╪══════════════════════╪═════╪═════╣ 
║ 1 │ 3 │ 2 │ {"f1": 1, "f2": "x"} │ 1 │ x ║ 
║ 5 │ 2 │ 3 │ {"f1": 2, "f2": "y"} │ 2 │ y ║ 
╚═══╧═══╧═══╧══════════════════════╧═════╧═════╝ 

Und für Ihre Daten könnte es sein:

select ProdName, j->>'f1' as val, j->>'f2' as fld 
from results, to_jsonb(least((d1,'d1'),(d2,'d2'),(d3,'d3'),...,(d10,'d10'))); 
0

für diese Antwort erstelle ich eine Tabelle mit 5 Preise

create temp table p (id text, p1 float, p2 float, p3 float, p4 float, p5 float); 
insert into p values ('Pizza', 1.4, 2, 1.3, 2.1, 1.6); 
insert into p values ('Tea', 1.4, 3, 3, 2.1, 1.6); 

Erste UNPIVOT dann Tabelle als Array mit den Namen der Woche und der Preis für jede Woche.

select 
    id, 
    unnest(array['week1','week2','week3','week4','week5']), 
    unnest(array[p1,p2,p3,p4,p5]) 
from p 

+-------+--------+--------+ 
| id | unnest | unnest | 
+-------+--------+--------+ 
| Pizza | week1 | 1,4 | 
+-------+--------+--------+ 
| Pizza | week2 | 2 | 
+-------+--------+--------+ 
| Pizza | week3 | 1,3 | 
+-------+--------+--------+ 
| Pizza | week4 | 2,1 | 
+-------+--------+--------+ 
| Pizza | week5 | 1,6 | 
+-------+--------+--------+ 
| Tea | week1 | 1,4 | 
+-------+--------+--------+ 
| Tea | week2 | 3 | 
+-------+--------+--------+ 
| Tea | week3 | 3 | 
+-------+--------+--------+ 
| Tea | week4 | 2,1 | 
+-------+--------+--------+ 
| Tea | week5 | 1,6 | 
+-------+--------+--------+ 

Dann filtern Sie diese Tabelle Ergebnis für den niedrigsten Preis.

where cte.price = (select least(p1,p2,p3,p4,p5) from p where p.id = cte.id); 

Sie können es hier ansehen: http://rextester.com/VKXK37428

with cte (id, week, price) as 
(
select 
    id, 
    unnest(array['week1','week2','week3','week4','week5']), 
    unnest(array[p1,p2,p3,p4,p5]) 
from p 
) 
select id, week, price 
from cte 
where cte.price = (select least(p1,p2,p3,p4,p5) from p where p.id = cte.id); 

Dies ist das Ergebnis:

+-------+-------+-------+ 
| id | week | price | 
+-------+-------+-------+ 
| Pizza | week3 | 1,3 | 
+-------+-------+-------+ 
| Tea | week1 | 1,4 | 
+-------+-------+-------+ 
+0

hallo. Update mit einer anderen Zeile und Gruppierung? 'Einfügen in p - Werte ('Tea', 1.9, 2, 1.3, 0.3, 1.6); 'Ich habe das Gefühl, die Frage war nicht über die einzige Zeile –

+0

Lassen Sie mich die Antwort bearbeiten – McNets

+0

Sie können es erneut überprüfen – McNets

0

Spät-. Es scheint wie ein Rad, aber trotzdem - so, wie es mit json zu tun:

a=# select * from results ; 
i | e | f | Prod .Name 
---+---+---+------------ 
2 | 1 | 3 | Pizza 
2 | 3 | 4 | Beer 
(2 rows) 

a=# select "Prod. Name","Lowest Price","From Week" from (
with p as (select "Prod .Name" as n,row_to_json(results) p from results) 
select 
    p.n as "Prod. Name" 
, min(case when j.value::text != concat('"',p.n,'"') then j.value::text::float end) over(partition by p.n) "Lowest Price" 
, case when j.value::text != concat('"',p.n,'"') then j.value::text::float end compare 
, j.key::text "From Week" 
from p, json_each(p.p) as j 
) s 
where compare = "Lowest Price" 
; 
Prod. Name | Lowest Price | From Week 
------------+--------------+----------- 
Beer  |   2 | i 
Pizza  |   1 | e 
(2 rows) 
Verwandte Themen