2011-05-22 15 views
48

Czy istnieje sposób ponownego użycia pola obliczeniowego w instrukcji mysql. I pojawia się błąd „nieznany kolumna total_sale” dla:Czy mogę ponownie użyć pola obliczeniowego w zapytaniu SELECT?

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

czy mam powtórzyć obliczenia, które pozwoliłoby na bardzo długi SQL jeśli dodałem wszystkie obliczenia potrzebne.

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

Oczywiście mogę wykonać wszystkie obliczenia w moim programie php.

Odpowiedz

61

Tak, można ponownie użyć zmiennych. Oto jak to zrobić:

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

Czytaj więcej na ten temat tutaj: http://dev.mysql.com/doc/refman/5.0/en/user-variables.html

[Uwaga: To zachowanie jest niezdefiniowane. Zgodnie z dokumentami MySQL:]

Zasadniczo nigdy nie należy przypisywać wartości do zmiennej użytkownika i odczytywać wartości w obrębie tej samej instrukcji. Możesz uzyskać oczekiwane wyniki, ale nie jest to gwarantowane.

+0

Hodowlana Kucyk Umysł? "@total_sale: =" czy to za mało deklaracji? – rzetterberg

+0

To ustawienie zmiennej, a nie deklarowanie jej. Deklaracja oznacza użycie instrukcji 'SET' lub pochodnego widoku tabela/wiersz. –

+1

"Można również przypisać wartość do zmiennej użytkownika w instrukcjach innych niż SET.W tym przypadku operator przypisania musi być: = i nie =, ponieważ ten drugi jest traktowany jako operator porównania = w instrukcjach innych niż SET:" – rzetterberg

5

Można użyć sub-select:

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; 
3

Można użyć podzapytania, podobnie jak to:

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 

Edit:
stałe iloczyn kartezjański, przy założeniu, że klucz podstawowy to id.
To powinno być równoważne z rozwiązaniem Kucyków OMG po zoptymalizowaniu, ale myślę, że będzie trudniej odczytać, jeśli potrzebujesz więcej podzapytań.

+1

Brak kryteriów łączenia oznacza produkt kartezjański ... –

+0

@OMG prawy ... jakoś sobie wyobrażałem, że chodziło tylko o jeden wiersz ... – kiw

8

tylko cross-platform obsługiwana środkiem jest za pomocą pochodzącą widoku tabeli/inline:

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 
35

Poniższy wydaje się działać dobrze w moich testów na MySQL 5.5:

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

Interesujące. Dlaczego to działa? –

+1

Podoba mi się to. Zdecydowanie najlepszą czytelność ze wszystkich odpowiedzi i brak ostrzeżeń o używaniu go w dokumentacji mysql. Nie można go jednak wykorzystać do odniesienia się do wyników grupy, takich jak wyniki uzyskane za pomocą SUMY lub COUNT. – David

+0

Ponieważ bieżąca zaakceptowana odpowiedź nie może działać za każdym razem, ta odpowiedź powinna być zaakceptowana. –

0

I zostały testowanie poniższych i wydaje się działać cały czas, być może jest ku temu powód, czy to dlatego, że wstępnie zdefiniowałem zmienną @total_sales jako wartość, a nie ciąg znaków, i nie zdefiniowałem ponownie jej typu podczas instrukcji select?

Gdybym wykonaj następujące czynności

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

musiałem spojrzeć na różnych odpowiedzi tu i zrobiliśmy kilka eksperymentów.

W szczególności używam MariaDB 10.1.

Przez „proste”, co można zrobić, co Robert D sugerował w swoim komentarzu:

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

Jeśli używasz jakiegoś funkcji zbiorczej z sprzężenie wewnętrzne nie mogą korzystać z tego, ale ty można połączyć to podejście z wewnętrzną dołączyć podejście następująco (NB „podatek od sprzedaży” VAT = ... i NB w polach danych finansowych w walucie zwykle mają 4 miejsc po przecinku, myślę, że to historyczny ...)

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 

Chciałem użyć powyższego, aby utworzyć View, aby wyświetlić listę faktur wi th ich podsumy, VAT i sumy ... okazało się, że MariaDB (i prawie na pewno MySQL) nie pozwala na zagnieżdżanie w klauzuli FROM. Jednak można to łatwo rozwiązać, tworząc pierwszy View, który zawiera listę InvoiceNo i Subtotal, a następnie tworzy drugi View, który odwołuje się do pierwszego. Z punktu widzenia wydajności nie mam pojęcia o tym rodzaju układu podwójnie-View.

Powiązane problemy