Это требование действительно плохо подходит для SQL, но это может быть достигнуто с большим количеством возиться с участием «динамического sql» и вымыванием для достижения эквивалента row_number(). т. е. Было бы легче достичь с помощью CTE и row_number(), возможно, если MySQL получит бит, это может быть повторно рассмотрено.
В любом случае, требуется получить цены в пронумерованные столбцы, поэтому первая цена каждого продукта идет в первом столбце, вторая цена во втором столбце и так далее. Поэтому нам нужно в первом случае указать число строк, которые впоследствии будут преобразованы в столбцы. В MySQL это можно сделать с помощью переменных, например:
select
@row_num := IF(@prev_value = p.id, @row_num+1, 1) AS RowNumber
, id
, price
, @prev_value := p.id
from (select distinct id, price from pricehistory) p
CROSS JOIN (SELECT @row_num :=1, @prev_value :='') vars
order by id, price
Так что фрагмент кода используется дважды в следующем. В верхней части он формирует набор выражений case, которые будут делать преобразование. В нижней части мы объединяем эти выражения case с остальной частью запрашиваемого sql и затем выполняем его.
set @sql = (
SELECT GROUP_CONCAT(col_ref)
FROM (
select distinct
concat(' max(case when RowNumber=',RowNumber,' then Price else NULL end) as c',RowNumber) col_ref
from (
select
@row_num := IF(@prev_value = p.id, @row_num+1, 1) AS RowNumber
, id
, price
, @prev_value := p.id
from (select distinct id, price from pricehistory) p
CROSS JOIN (SELECT @row_num :=1, @prev_value :='') vars
order by id, price
) d
order by `RowNumber`
) dc
);
set @sql = concat('select id,', @sql,
' from (
select
@row_num := IF(@prev_value = p.id, @row_num+1, 1) AS RowNumber
, id
, price
, @prev_value := p.id
from (select distinct id, price from pricehistory) p
CROSS JOIN (SELECT @row_num :=1, @prev_value :='''') vars
order by id, price
) d
Group By `id`');
#select @sql
PREPARE stmt FROM @sql;
EXECUTE stmt;
\\
В результате этого, на основе выборки заданного является:
id c1 c2 c3
1 1 23 NULL NULL
2 2 14 20 23
3 3 30 40 NULL
Это решение может быть проверено и повторно запустить по адресу: http://rextester.com/AYAA36866
Примечание полностью генерируется SQL читается как это :
select id
, max(case when RowNumber=1 then Price else NULL end) as c1
, max(case when RowNumber=2 then Price else NULL end) as c2
, max(case when RowNumber=3 then Price else NULL end) as c3
from (
select
@row_num := IF(@prev_value = p.id, @row_num+1, 1) AS RowNumber
, id
, price
, @prev_value := p.id
from (select distinct id, price from pricehistory) p
CROSS JOIN (SELECT @row_num :=1, @prev_value :='') vars
order by id, price
) d
Group By `id`
Существует мало потребности в желаемом желании в наборе на основе языка. Вы ищете запрос кросс-таблицы, который в настоящее время не существует в mysql. Оформить заказ http://stackoverflow.com/questions/15997090/crosstab-view-in-mysql –
Возможно, вы обнаружили, что поиск возвращаемого xml из mysql полезен. Достаточно просто преобразовать xml в json, если вы хотите использовать данные в веб-браузере. https://www.google.com.au/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=mysql%20return%20xml –
Простой GROUP_CONCAT, как в решении @ RicardoOrtegaMagaña, или если вы хотите его отдельные столбцы это можно сделать, но вы должны заранее определить количество столбцов. –