2011-05-22 2 views
48

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

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.

ответ

61

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

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

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

+0

@OMG Ponies Mind разработка? "@total_sale: =" - это недостаточно объявление? – rzetterberg

+0

Это настройка переменной, а не объявление ее. Объявление означает либо использование оператора 'SET', либо производного таблицы/встроенного представления. –

+1

«Вы также можете присвоить значение переменной пользователя в операторах, отличных от SET. В этом случае оператор присваивания должен быть: = и not =, потому что последний рассматривается как оператор сравнения = в операторах без SET:« – rzetterberg

5

Вы можете использовать суб-выбор:

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

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

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

+1

Критерии присоединения не относятся к картезианскому продукту ... –

+0

@OMG right ... каким-то образом я представил себе, что это было всего лишь одна строка ... – kiw

8

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

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

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

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

Интересно. Почему это работает? –

+1

Мне это нравится. Безусловно, лучшая читаемость из всех ответов и отсутствие предупреждений об использовании этого в документации mysql. Однако он не может использоваться для ссылки на результаты группы, такие как те, которые вы получаете с помощью SUM или COUNT. – David

+0

Поскольку текущий принятый ответ не может работать каждый раз, это может быть принятый ответ –

0

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

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

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

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

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

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

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

Если вы используете какое-то агрегатная функцию с внутренним соединением вы не можете использовать это, но вы может сочетать этот подход с внутренним соединением подход следующим образом (NB «налог с продаж» НДС = ... и 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, чтобы перечислить счета-фактуры wi их промежуточных итогов, НДС и итогов ... выяснилось, что MariaDB (и почти наверняка MySQL) не допускает вложения в предложение FROM. Однако это легко решить, сделав первый View, который перечисляет InvoiceNo и Subtotal, а затем делает второй View, который ссылается на первый. По правде говоря, я вообще не знаю, как это устроено в двухэтажном варианте: View.

Смежные вопросы