2017-01-06 3 views
0

haben eine SQL-Abfrage wie folgt aus:MySQL, Gruppe sowohl in der inneren und äußeren Abfrage zur gleichen Zeit

SELECT position, AVG(price) FROM products WHERE position IS NOT NULL 
AND price < (SELECT AVG(price)+2*STDDEV(price) FROM price) 
AND position = 3 

Schön, wenn Sie nur eine Position zu der Zeit überprüfen möchten, aber ich habe eine ganz wenige Positionen und ich möchte daher die Daten für alle Positionen zur gleichen Zeit erhalten.

das heißt so etwas wie:

[QUERY]... GROUP BY position 

Aber wie kann ich Gruppe von Position sowohl in der inneren und der äußeren Abfrage, so dass es innere Abfrage where-Klausel einen Wert zurückgeben, der die richtige Position übereinstimmt.

Danke.

+0

Siehe http://meta.stackoverflow.com/questions/333952/why-should-i-provide-an-mcve-for-what-seems-to-me-to-be-very-simple- sql-query – Strawberry

+0

Warum die -1 Bewertung? – Louisa

+0

Bewegen Sie den Mauszeiger über den Abwärtspfeil. – Strawberry

Antwort

1

Sie suchen nach GROUP BY. Um den Durchschnittspreis für jede Position und nicht nur für eine Position zu erhalten, gehen Sie wie folgt vor.

SELECT position, AVG(price) average 
    FROM products 
GROUP BY position 

Sie haben einen Zwei-Sigma-Ausschluss in Ihrer Abfrage. Sie müssen die gleiche Technik verwenden, um das Limit für jede Position zu erhalten. Wenn Sie den Mittelwert + 2 Sigma-Grenzwert für jede Position berechnen möchten, benötigen Sie diese Unterabfrage. (Hinweis: Es ist am besten eher Klammern in Sprachen wie SQL zu verwenden, als arithmetischen Operator Vorrang zu vertrauen.)

    SELECT position, 
         AVG(price) + (2.0 * STDDEV(price)) upper_limit 
        FROM products 
        GROUP BY position 

Sie dann diese Abfrage auf Ihr Top-Level kommen können wie wählen so

SELECT a.position, a.price 
    FROM products 
    JOIN (
       SELECT position, 
         AVG(price) + (2.0 * STDDEV(price)) upper_limit 
        FROM products 
        GROUP BY position 
     ) b ON a.position = b.position 
      AND a.price < b.upper_limit 

Das gibt Ihnen die Rohdaten für Position/Preis ohne Ihre Ausreißer. Sehen Sie, wie die -Klausel den Zeilen in der Haupt- und Unterabfrage nach Position entspricht, und filtert dann die Zeilen heraus, in denen der Rohpreis über der upper_limit liegt? Das ist der Trick.

Dann können Sie diese Daten mit einem typischen GROUP BY aggregieren.

SELECT a.position, AVG(a.price) average 
    FROM products 
    JOIN (
       SELECT position, 
         AVG(price) + (2.0 * STDDEV(price)) upper_limit 
        FROM products 
        GROUP BY position 
     ) b ON a.position = b.position 
      AND a.price < b.upper_limit 
    GROUP BY a.position 

Diese Schichtung von Unterabfragen innerhalb von Abfragen ist, warum es strukturierte Abfragesprache genannt wird.

+0

Perfekt. Danke vielmals! – Louisa

0

Wird GROUP BY nicht hinzugefügt, was Sie wollen?

SELECT position, AVG(price) 
FROM products p 
WHERE position IS NOT NULL AND 
     price < (SELECT AVG(price)+2*STDDEV(price) 
       FROM price p2 
      ) 
GROUP BY position; 

Oder gibt es ein bestimmtes Produkt, das Ihnen wichtig ist? Wenn ja, möchten Sie eine korrelierte Unterabfrage:

SELECT position, AVG(price) 
FROM products p 
WHERE position IS NOT NULL AND 
     price < (SELECT AVG(price)+2*STDDEV(price) 
       FROM price p2 
       WHERE p.? = p2.? 
      ) 
GROUP BY position; 

Es ist nur unklar, welche Spalte für die Korrelation verwendet werden soll.

+0

Danke, aber die oberste Abfrage beschränkt die stddev nicht auf die aktuelle Position (d. H. Jede der Positionen, nach denen wir gruppieren). Also statt stddev für die aktuelle Position zu filtern, filtern wir für die Stddev aller Zeilen in der Tabelle. – Louisa

Verwandte Themen