2015-12-05 4 views
3

Я прочитал несколько потоков здесь подзапрос повторного использования, но не смог найти удовлетворительный ответ на мой вопрос: Предполагая следующую таблицу темпа (в MySQL):MySQL Повторного использование подзапросов

+------+---+----+ 
| Y | M | V | 
+------+---+----+ 
| 1995 | 0 | 3 | 
| 1995 | 1 | 16 | 
| 1995 | 4 | 18 | 
| 2025 | 0 | 4 | 
| 2025 | 2 | 13 | 
+------+---+----+ 

Я хотел бы создать новый столбец X, который копирует V из строки, где М равно 0 во всех строках с одинаковым Y (ухо), например:

+------+---+----+------+ 
| Y | M | V | X | 
+------+---+----+------+ 
| 1995 | 0 | 3 | 3 | 
| 1995 | 1 | 16 | 3 | 
| 1995 | 4 | 18 | 3 | 
| 2025 | 0 | 4 | 4 | 
| 2025 | 2 | 13 | 4 | 
+------+---+----+------+ 

Это может быть сделано, как это :

SELECT Y, M, V, 
    (SELECT V FROM temp WHERE temp.Y = t.Y AND M = 0) AS X 
FROM temp t; 

или как это:

SELECT temp.Y, temp.M, temp.V, q2.V AS X 
FROM temp 
JOIN (SELECT * FROM temp WHERE M = 0) q2 USING (Y); 

Для целей этого упражнения можно предположить, что температура содержит только один М = 0 для каждого Y (ухо).

Проблема в том, что temp на самом деле не таблица, а результат сложного запроса. Замена temp на фактический запрос громоздка, и производительность, вероятно, будет плохой, если только MySQL не станет достаточно умным, чтобы обнаружить, что две конструкции идентичны.

Нет предложения WITH в MySQL, есть ли способ генерировать X без необходимости ссылаться на temp дважды; т. е. является подзапросом, действительно необходимым для этой проблемы?

Код, в конечном счете, будет запущен внутри S-PROC, поэтому я мог бы создать временную таблицу памяти, но мне интересно, есть ли более элегантное решение.

+0

Как вы уже выяснили, mysql не поддерживает Common Table Expressions, как бы то ни было, чего вы пытаетесь достичь, возможно, с вложенными подзапросами. – e4c5

+0

будет иметь вид справки, это не таблица, но действует как один в запросах – davejal

+0

Thx. У меня ограниченный опыт просмотра. Не уверены, могут ли они принимать переменные, поскольку сложный запрос зависит от параметра. – Matthias

ответ

2

Общепринятые выражения таблиц и подзапросы - это самый простой способ. Представление - это одно решение. Другой способ заключается в использовании переменных:

select t.*, 
     (@v := if(@y = y, @v, 
       if(@y := y, v, v) 
       ) 
     ) 
from temp t cross join 
    (select @y := 0, @v := -1) params 
order by year, (m = 0) desc; 

Обратите внимание, что эта формулировка делает сильное предположение о том, что каждый год имеет по крайней мере одно значение m = 0 - копирует первое значение встречается на каждый год для всех строк на этот год. Вы указываете, что это верно в описании проблемы. Выражение может быть сделано несколько сложнее, чтобы охватить ситуацию, когда год не имеет такой строки (но это был бы другой вопрос).

+0

Thx, это работает и выглядит многообещающим, поскольку temp появляется только один раз. Мне нужно понять, что на самом деле происходит :-) BTW, заказ не является существенным для этой проблемы. – Matthias

+0

@ Matthias. , , 'orer by' необходим для работы логики. Он должен найти 'm = 0' за данный год до других значений' m' за этот год. –

+0

Полезно знать, thx Gordon. Кстати, физический порядок создает упорядоченные Ys с ведущим m = 0, но это может быть не всегда так, и важно для любого другого повторного использования этого элегантного решения. (По-прежнему не удалось понять, почему это работает так, как это происходит, потому что мне нужно адаптировать его к реальной проблеме, где мне нужно совместить больше, чем просто Y, и более одного V (alue) необходимо скопировать из M = 0 строка. :-) – Matthias

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