Ich habe eine Postgres-Tabelle mit Produktdaten verschiedener Hersteller, hier die vereinfachte Tabellenstruktur:
CREATE TABLE test_table (
sku text,
manufacturer_name text,
price double precision,
stock int
);
INSERT INTO test_table
VALUES ('sku1', 'Manufacturer1', 110.00, 22),
('sku1', 'Manufacturer2', 120.00, 15),
('sku1', 'Manufacturer3', 130.00, 1),
('sku1', 'Manufacturer3', 30.00, 11),
('sku2', 'Manufacturer1', 10.00, 2),
('sku2', 'Manufacturer2', 9.00, 3),
('sku3', 'Manufacturer2', 21.00, 3),
('sku3', 'Manufacturer2', 1.00, 7),
('sku3', 'Manufacturer3', 19.00, 5);
Ich muss jeden Hersteller für jede SKU ausgeben, aber wenn es mehrere identische Hersteller für dieselbe SKU gibt, muss ich den Hersteller mit dem niedrigsten Preis auswählen (beachten Sie, dass ich auch die Spalte "Lager" einfügen muss), hier gewünschte Ergebnisse:
| sku | man1_price | man1_stock | man2_price | man2_stock | man3_price | man3_stock |
|------|------------|------------|------------|------------|------------|------------|
| sku1 | 110.0 | 22 | 120.0 | 15 | 30.0 | 11 |
| sku2 | 10.0 | 2 | 9.0 | 3 | | |
| sku3 | | | 1.0 | 7 | 19.0 | 5 |
Ich habe versucht, Postgres zu verwenden crosstab()
:
SELECT *
FROM crosstab('SELECT sku, manufacturer_name, price
FROM test_table
ORDER BY 1,2',
$$ SELECT DISTINCT manufacturer_name FROM test_table ORDER BY 1 $$
)
AS ct (sku text, "man1_price" double precision,
"man2_price" double precision,
"man3_price" double precision
);
Dies erzeugt jedoch eine Tabelle mit nur einer price
Spalte. Und ich habe keine Möglichkeit gefunden, die stock
Spalte einzuschließen.
Ich habe auch versucht, die bedingte Aggregation zu verwenden:
SELECT sku,
MIN(CASE WHEN manufacturer_name = 'Manufacturer1' THEN price END) as man1_price,
MIN(CASE WHEN manufacturer_name = 'Manufacturer1' THEN stock END) as man1_stock,
MIN(CASE WHEN manufacturer_name = 'Manufacturer2' THEN price END) as man2_price,
MIN(CASE WHEN manufacturer_name = 'Manufacturer2' THEN stock END) as man2_stock,
MIN(CASE WHEN manufacturer_name = 'Manufacturer3' THEN price END) as man3_price,
MIN(CASE WHEN manufacturer_name = 'Manufacturer3' THEN stock END) as man3_stock
FROM test_table
GROUP BY sku
ORDER BY sku
Und diese Abfrage funktioniert auch in meinem Fall nicht - sie wählt einfach den Mindestbestand aus - aber wenn es nur wenige gleiche Hersteller für denselben Artikel, aber mit unterschiedlichen Preisen / Lagerbeständen gibt, wählt diese Abfrage den Mindestpreis eines Herstellers und den Mindestbestand aus Ein weiterer.
Wie kann ich die price
entsprechenden und entsprechenden Hersteller stock
aus dieser Tabelle ausgeben ?
PS Vielen Dank für diese hilfreichen Antworten. Meine Postgres-Tabelle ist ziemlich klein - es gibt nicht mehr als 15.000 Produkte (ich weiß nicht, ob solche Zahlen für einen korrekten Vergleich nützlich sein können), aber da Erwin Brandstetter darum gebeten hat, die Leistung verschiedener Abfragen zu vergleichen, mit denen ich 3 Abfragen ausgeführt habe EXPLAIN ANALYZE
, sind hier ihre Ausführungszeit:
Erwin Brandstetter query: 400 - 450 ms
Kjetil S query: 250 - 300 ms
Gordon Linoff query: 200 - 250 ms
a_horse_with_no_name query: 250 - 300 ms
Nochmals - ich bin mir nicht sicher, ob diese Zahlen als Referenz nützlich sein können. Für meinen Fall wähle ich die kombinierte Version Kjetil S
und Gordon Linoff
Abfragen aber Erwin Brandstetter
und a_horse_with_no_name
Varianten sind auch sehr nützlich und interessant. Es ist erwähnenswert, dass, wenn meine Tabelle in Zukunft mehr als wenige Hersteller haben würde - das Anpassen der Abfrage und das Eingeben ihrer Namen jedes Mal wäre mühsam - und daher die Abfrage aus der a_horse_with_no_name
Antwort am bequemsten zu verwenden wäre.
Ihre letzte Auswahl funktioniert fast . Sie sollten jedoch eine where-Bedingung hinzufügen, bei der Zeilen mit nicht minimalen Preisen pro SKU und Hersteller entfernt werden. Dies führt zu Ihrem erwarteten Ergebnis:
select
sku,
min( case when manufacturer_name='Manufacturer1' then price end ) man1_price,
min( case when manufacturer_name='Manufacturer1' then stock end ) man1_stock,
min( case when manufacturer_name='Manufacturer2' then price end ) man2_price,
min( case when manufacturer_name='Manufacturer2' then stock end ) man2_stock,
min( case when manufacturer_name='Manufacturer3' then price end ) man3_price,
min( case when manufacturer_name='Manufacturer3' then stock end ) man3_stock
from test_table t
where not exists (
select 1 from test_table
where sku=t.sku
and manufacturer_name=t.manufacturer_name
and price<t.price
)
group by sku
order by 1;
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen