2011-01-13 12 views
0

ich zwei Abfragen, die eine einzelne Spalte mit doppelter Genauigkeit Werte zurück:Abteilung in SQL Query Statement

(SELECT scale 
    FROM (SELECT title, 
       scale, 
       dense_rank() OVER (PARTITION BY title 
             ORDER BY scale ASC) AS r 
      FROM signatures) t 
    WHERE r = 1) 

... und:

(SELECT scale 
    FROM (SELECT scale, 
       dense_rank() OVER (PARTITION BY title 
             ORDER BY scale ASC) AS r 
      FROM signatures) t 
    WHERE r = 2) 

Ich versuche, die erste Abfrage SELECT (Q1) geteilt durch die zweite Abfrage (Q2). D.h., (Reihe 1 von Q1)/(Reihe 1 von Q2). Und fuhr den Rest der Reihen fort.

Ich habe versucht:

SELECT ((SELECT scale 
      FROM (SELECT title, 
         scale, 
         dense_rank() OVER (PARTITION BY title 
               ORDER BY scale ASC) AS r 
        FROM signatures) t 
      WHERE r = 1) 

/

(SELECT scale 
    FROM (SELECT scale, 
       dense_rank() OVER (PARTITION BY title 
             ORDER BY scale ASC) AS r 
      FROM signatures) t 
    WHERE r = 2) 
) 

Aber habe kein Glück gehabt. Kann jemand einen Weg sehen, dies zu tun? Ich kann die zwei Abfragen separat senden, dann durchlaufen Sie eine Schleife und teilen Sie die Elemente, aber das funktioniert nicht für ein semi-großes Recordset.

Auch sollte es nicht wichtig sein, aber ich benutze PostgreSQL.

+1

Sie erkennen, dass 'DENSE_RANK' den gleichen Wert zurückgibt, wenn Sie mit Bindungen arbeiten? Zum Beispiel könnten Sie drei Instanzen für den zweiten Platz gebunden haben, was zu Trauer in Ihrer Abteilung führt ... –

+0

@OMG. Ok, aber wenn ich die Abfragen getrennt ausführe, erhalte ich korrekte Spaltenergebnisse. Ist es nicht möglich, diese beiden in einer einzigen Aussage zu teilen? – Brett

+0

Kann ich eine lokale temporäre Tabelle definieren, um die Ergebnisspalten für jede Abfrage zu speichern, und diese dann multiplizieren? – Brett

Antwort

1

Ich denke, dass Sie die LEAD Fensterfunktion verwenden möchten, anstatt zwei Sätze zu bekommen und zu versuchen, ihnen beizutreten. Dadurch können Sie auf eine andere Zeile im selben Fenster verweisen (d. H. Mit einer übereinstimmenden partition by). Etwas wie:

select title, scale/next_scale 
from (select title, scale, 
       lead(scale) over(partition by title order by scale asc) as next_scale, 
       row_number() over(partition by title order by scale asc) as agg_row 
     from signatures 
    ) agg 
where agg_row = 1; 

Hier nimmt lead(scale) den Wert aus der Spalte von scale nächsten Zeile Ausgang im selben Fenster zu sein, das heißt, die nächste am weitesten Skala um. Wir müssen immer noch row_number() projizieren und danach filtern, so dass wir nur Ausgangszeilen für die erste Zeile in jedem Fenster erhalten, d. H. Die Zeile mit der geringsten Skalierung für jeden Titel.

+0

Erstaunlich! Funktioniert perfekt. Ich hatte die LEAD-Funktion vorher noch nicht benutzt, so dass ich sogar etwas Neues gelernt habe;) Ganz zu schweigen von der Abfrage ist deutlich schneller als das Ausführen von Zwei und Verbinden. Vielen, vielen Dank! – Brett

0

Sie müssen SQL eine Möglichkeit geben zu wissen, welche Zahl in jeder Spalte durch welche geteilt wird. Versuchen Sie folgendes:

SELECT first.title, (first.scale/second.scale) ratio 
     FROM 
      (SELECT scale, title 
       FROM (SELECT title, scale, 
          dense_rank() OVER 
          (PARTITION BY title ORDER BY scale ASC) AS r 
         FROM signatures) t 
      WHERE r = 1) first 
INNER JOIN 
      (SELECT scale, title 
       FROM (SELECT title, scale, 
          dense_rank() OVER 
          (PARTITION BY title ORDER BY scale ASC) AS r 
         FROM signatures) t 
      WHERE r = 2) second 
     ON first.title = second.title 

Wie OMG kommentierte DENSE_RANK können Sie Schwierigkeiten, wenn Sie mit mehreren gleichen Skalenwerten enden. Möglicherweise möchten Sie jede Unterabfrage auf eine Zeile pro Titel beschränken, wenn dies für Ihre Logik geeignet ist, oder alternativ SELECT DISTINCT in der äußeren Abfrage angeben, da die Duplikate exakte Duplikate sind.