Можно ли повторно использовать вычисляемое поле в запросе SELECT?

Есть ли способ повторно использовать вычисляемое поле в операторе 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 ответов

Решение

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

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:]

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

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

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

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

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

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

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;

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

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 после оптимизации, но я думаю, что будет труднее читать, если вам нужно больше подзапросов.

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

В частности, я использую 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 расположение.

Я тестировал следующее, и оно, кажется, работает все время, возможно, есть причина для этого, потому что я предопределил переменную @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
Другие вопросы по тегам