web-dev-qa-db-de.com

Kann ich ein berechnetes Feld in einer SELECT-Abfrage wiederverwenden?

Gibt es eine Möglichkeit, ein berechnetes Feld in einer mysql-Anweisung wiederzuverwenden. Ich erhalte den Fehler "unbekannte Spalte total_sale" für:

SELECT 
    s.f1 + s.f2 as total_sale, 
    s.f1 / total_sale as f1_percent
FROM sales s

oder muss ich die Berechnung wiederholen, was zu einer sehr langen SQL-Anweisung führen würde, wenn ich alle erforderlichen Berechnungen hinzufügt.

SELECT 
    s.f1 + s.f2 as total_sale, 
    s.f1 / (s.f1 + s.f2) as f1_percent
FROM sales s

natürlich kann ich alle Berechnungen in meinem PHP-Programm durchführen.

58
sdfor

Ja, Sie können Variablen wiederverwenden. Das ist wie man es macht: 

SELECT 
    @total_sale := s.f1 + s.f2 as total_sale, 
    s.f1 / @total_sale as f1_percent
FROM sales s

Lesen Sie mehr darüber hier: http://dev.mysql.com/doc/refman/5.0/de/user-variables.html

[Hinweis: Dieses Verhalten ist undefiniert. Laut den MySQL-Dokumenten:]

In der Regel sollten Sie niemals einer Benutzervariable einen Wert zuweisen und den Wert innerhalb derselben Anweisung lesen. Sie erhalten möglicherweise die erwarteten Ergebnisse, dies ist jedoch nicht garantiert.

70
rzetterberg

Folgendes scheint bei meinen Tests mit MySQL 5.5 gut zu funktionieren:

SELECT 
    s.f1 + s.f2 as total_sale, 
    s.f1 / (SELECT total_sale) as f1_percent
FROM sales s
47
Robert D

Nur plattformübergreifend unterstützte Mittel sind die Verwendung einer abgeleiteten Tabelle/Inline-Ansicht

SELECT x.total_sale,
       x.f1 / x.total_sale as f1_percent
  FROM (SELECT s.f1,
               s.f1 + s.f2 as total_sale, 
          FROM sales s) x
12
OMG Ponies

Sie können eine Unterauswahl verwenden:

select tbl1.total_sale,
       tbl1.f1/tbl1.total_sale as f1_percent 
  from (select s.f1+s.f2 AS total_sale, 
               s.f1 
          from sales s) as tbl1;
6
AJ.

Sie können Unterabfragen wie folgt verwenden:

SELECT 
    h.total_sale, 
    s.f1 / h.total_sale AS f1_percent
FROM sales s,
    (SELECT id, f1 + f2 AS total_sale FROM sales) h
WHERE
    s.id = h.id

Bearbeiten:
Festes kartesisches Produkt, vorausgesetzt, der Primärschlüssel ist id.
Dies sollte der Lösung von OMG Ponies nach der Optimierung entsprechen, aber ich denke, es wird schwieriger zu lesen, wenn Sie weitere Unterabfragen benötigen.

4
kiw

Ich habe mir hier verschiedene Antworten angesehen und ein paar Experimente durchgeführt.

Insbesondere verwende ich MariaDB 10.1.

Für eine "einfache" Sache können Sie tun, was Robert D in seinem Kommentar vorgeschlagen hat:

SELECT Price_Per_SqFt, (Price_Per_SqFt/2) AS col1, (SELECT col1 + 1) AS col2 FROM Items 

Wenn Sie eine Art Aggregatfunktion mit einem Inner Join verwenden, können Sie diese Funktion nicht verwenden. Sie können diesen Ansatz jedoch wie folgt mit dem Inner Join-Ansatz kombinieren (NB VAT = "sales tax" ... und NB in Finanzdatenwährungsfeldern haben normalerweise 4 Dezimalstellen, ich denke, es ist historisch ...)

SELECT 
    invoices.invoiceNo, invoices.clientID, invoices.Date, invoices.Paid, 
  invoicesWithSubtotal.Subtotal,
  ROUND( CAST( Subtotal * invoices.VATRate AS DECIMAL( 10, 4 )), 2 ) AS VAT,
  (SELECT VAT + Subtotal) AS Total
FROM invoices 
    INNER JOIN 
    ( SELECT Sum( invoiceitems.Charge ) AS Subtotal, invoices.InvoiceNo FROM invoices 
        INNER JOIN invoiceitems ON invoices.InvoiceNo = invoiceitems.InvoiceNo
            GROUP BY invoices.InvoiceNo ) invoicesWithSubtotal
    ON invoices.InvoiceNo = invoicesWithSubtotal.InvoiceNo

Ich wollte das oben genannte verwenden, um eine View zu erstellen, um Rechnungen mit ihren Zwischensummen, Mehrwertsteuer und Gesamtsummen aufzulisten. Es stellte sich heraus, dass MariaDB (und mit ziemlicher Sicherheit MySQL) keine Verschachtelung in der FROM Klausel. Dies kann jedoch leicht gelöst werden, indem ein erstes View erstellt wird, in dem InvoiceNo und Subtotal aufgelistet sind, und dann ein zweites View erstellt wird, das auf das erste verweist. In Bezug auf die Performance habe ich überhaupt keine Ahnung von dieser Art von Doppel - View - Arrangement.

0
mike rodent

Ich habe das Folgende getestet und es scheint die ganze Zeit zu funktionieren, vielleicht gibt es einen Grund dafür, weil ich die Variable @total_sales als Wert und nicht als String vordefiniert habe und ihren Typ während der Auswahl nicht neu definiert habe Aussage ??

Wenn ich folgendes mache

    set @total_sales = 0;

    SELECT 
       @total_sale := s.f1 + s.f2 as total_sale, 
      s.f1 / @total_sale as f1_percent
   FROM sales s
0
Lawrence Edel