2017-11-25 1 views
0

Ich versuche, die Termine von string_agg in neuen SpaltenSQL-Spalten hinzufügen, basierend auf der Anzahl der Ergebnisse

SELECT g.ganado_id, 
     string_agg(i.date, ', ') AS date 
FROM inseminacion i 
     INNER JOIN ganado g 
      ON g.ganado_id = i.ganado_id 
GROUP BY g.ganado_id 

tatsächliche Ausgang

|ganado_id|date        | 
|1  |2016-10-15       | 
|2  |2016-10-15, 2017-02-15    | 
|3  |2016-10-15, 2017-03-09, 2017-05-27 | 
|4  |2017-06-02       | 

Wunsch Ausgang

|ganado_id|date1  |date2  |date3  | 
|1  |2016-10-15 |   |   | 
|2  |2016-10-15 |2017-02-15 |   | 
|3  |2016-10-15 |2017-03-09 |2017-05-27 | 
|4  |2017-06-02 |   |   | 

hinzufügen Meine erster Eindruck war Pivot-Tabelle zu verwenden, aber ich kann nicht herausfinden, wie

+0

posten Bitte, die Daten in Tabellen – SEarle1986

Antwort

1

Erwägen läuft string_agg() nicht aber bedingte Aggregation mit einer Zeilennummer auszuführen:

WITH cte AS 
    (SELECT g.ganado_id, i.date, 
      ROW_NUMBER() OVER 
      (PARTITION BY g.ganado_id ORDER BY i.date) AS grp_num 
    FROM inseminacion i 
    INNER JOIN ganado g ON g.ganado_id = i.ganado_id) 

SELECT c.ganado_id 
     MAX(CASE WHEN c.grp_num = 1 THEN c.date ELSE NULL END) AS date1, 
     MAX(CASE WHEN c.grp_num = 2 THEN c.date ELSE NULL END) AS date2, 
     MAX(CASE WHEN c.grp_num = 3 THEN c.date ELSE NULL END) AS date3 
FROM cte c 
GROUP BY c.ganado_id 
+0

gibt es eine Möglichkeit Spalte date3 falls alle Ergebnisse null sind zu verbergen? Zeigen Sie auch ein zusätzliches Datum4, falls es existiert? – danielctf

+0

Sie können die Zeilen MAX (...) beliebig erweitern. Wie zum Ausblenden/Anzeigen von Spalten ist SQL eine deklarative Spezialzwecksprache, in der Spalten strukturelle Komponenten sind, wie hier zu sehen ist, die fest codiert sind. Sobald eine Anweisung deklariert ist, ist sie unveränderlich. Resultsets können die Spaltenstruktur nicht in Abhängigkeit von Daten ändern. Zeilen können zwar bedingt durch Daten gefiltert werden. – Parfait

0

Sie brauchen nicht beide Tabellen für Ihre Anfrage. . . in anderen Worten, die join nicht notwendig:

SELECT i.ganado_id, 
     MAX(i.date) FILTER (WHERE seqnum = 1) as date_1, 
     MAX(i.date) FILTER (WHERE seqnum = 2) as date_2, 
     MAX(i.date) FILTER (WHERE seqnum = 3) as date_3 
FROM (SELECT i.*, 
      ROW_NUMBER() OVER (PARTITION BY i.ganado_id ORDER BY i.date ASC) as seqnum 
     FROM inseminacion i 
    ) i 
GROUP BY i.ganado_id; 
+0

Ich denke, wenn es Datensätze in 'inseminacion' gibt, die nicht in' ganado' sind, dann würde der Join einen Unterschied in der Ausgabe machen. Wenn nicht (nur das OP weiß das), dann würde ich dir zustimmen – Hambone

+0

@Hambone. . . Technisch wahr. Aber es ist eine vernünftige Annahme, dass das Feld namens "ganado_id" zwischen den beiden Tabellen übereinstimmen würde. –

0

Ich weiß, Sie schon eine Antwort haben, aber zum Wohle der anderen, die ein ähnliches Problem haben kann, würde ich als Alternative den Einsatz von PostgreSQL bieten hervorragende Arrays, eine der Funktionen, die es mir schwer macht, zu einem anderen DBMS zurückzukehren.

SELECT g.ganado_id, 
     array_agg(i.date) AS dates 
FROM inseminacion i 
     INNER JOIN ganado g 
      ON g.ganado_id = i.ganado_id 
GROUP BY g.ganado_id 

Für sich genommen könnte dies tatsächlich Ihren Bedarf erfüllen. Es hat den zusätzlichen Vorteil, dass es sehr skalierbar ist. Wenn Ihr Array also über drei Elemente hinausgeht, müssen Sie nichts ändern.

Auch, wenn Sie es mit dem Format, das Sie aufgeführt zu konvertieren benötigt, wäre es eine relativ einfache Aufgabe sein:

with cte as (
    SELECT g.ganado_id, 
      array_agg(i.date) AS dates 
    FROM inseminacion i 
      INNER JOIN ganado g 
       ON g.ganado_id = i.ganado_id 
    GROUP BY g.ganado_id 
) 
select 
    ganado_id, dates[1], dates[2], dates[3] 
from cte 

Und natürlich, wenn der Tag kommt, wenn Sie einen vierten und fünften Tag haben, es wäre so einfach sein wie:

select 
    ganado_id, dates[1], dates[2], dates[3], dates[4], dates[5] 
from cte 
Verwandte Themen