Можно ли повторно использовать вычисляемое поле в запросе SELECT? - PullRequest
59 голосов
/ 22 мая 2011

Есть ли способ повторно использовать вычисляемое поле в операторе mysql.Я получаю сообщение об ошибке «неизвестный столбец total_sale» для:

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

или мне приходится повторять вычисления, что может привести к очень длинному оператору SQL, если я добавлю все необходимые вычисления.

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

Конечно, я могу делать все вычисления в моей программе PHP.

Ответы [ 7 ]

72 голосов
/ 22 мая 2011

Да, вы можете повторно использовать переменные. Вот как вы это делаете:

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

Подробнее об этом здесь: http://dev.mysql.com/doc/refman/5.0/en/user-variables.html

[Примечание: это поведение не определено. Согласно документации MySQL:]

Как правило, вы никогда не должны присваивать значение пользовательской переменной и читать значение в том же выражении. Вы можете получить ожидаемые результаты, но это не гарантируется.

47 голосов
/ 06 января 2015

В моем тестировании на MySQL 5.5, похоже, хорошо работает следующее:

SELECT 
    s.f1 + s.f2 as total_sale, 
    s.f1 / (SELECT total_sale) as f1_percent
FROM sales s
13 голосов
/ 22 мая 2011

Только кроссплатформенное средство поддерживается с помощью производной таблицы / встроенного представления:

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
6 голосов
/ 22 мая 2011

Вы можете использовать дополнительный выбор:

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;
4 голосов
/ 22 мая 2011

Вы можете использовать подзапросы, например:

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

Редактировать:
фиксированное декартово произведение, предполагая, что первичный ключ равен id.
Это должно бытьэквивалентно решению OMG Ponies после оптимизации, но я думаю, что будет труднее читать, если вам нужно больше подзапросов.

0 голосов
/ 26 октября 2017

Я посмотрел различные ответы здесь и провел несколько экспериментов.

В частности, я использую MariaDB 10.1.

Для «простой» вещи вы можете сделать то, что Роберт Д. предложил в своем комментарии:

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

Если вы используете какую-то агрегатную функцию с внутренним объединением, вы не можете использовать это, но вы можете объединить этот подход с подходом внутреннего объединения следующим образом (NB VAT = "налог с продаж" ... и NB в Поля валюты финансовых данных обычно имеют 4 знака после запятой, я думаю, что это исторический ...)

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

Я хотел использовать вышеупомянутое, чтобы создать View для перечисления счетов-фактур с их промежуточными итогами, НДС и итогами ... оказалось, что MariaDB (и почти наверняка MySQL) не разрешают вложение в предложении FROM , Однако это легко решается путем создания первого View, в котором перечислены InvoiceNo и Subtotal, а затем создания второго View, который ссылается на первое. Что касается производительности, я понятия не имею об этом виде двойной View договоренности.

0 голосов
/ 15 августа 2016

Я тестировал следующее, и оно, кажется, работает все время, возможно, есть причина для этого, потому что я предопределил переменную @total_sales как значение, а не строку, и не переопределил ее тип во время выбора оператора ??

Если я сделаю следующее

    set @total_sales = 0;

    SELECT 
       @total_sale := s.f1 + s.f2 as total_sale, 
      s.f1 / @total_sale as f1_percent
   FROM sales s
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...