假设我有一张产品价格历史表,这是价格和产品ID,并附有以下记录:
id price
1 23
2 14
2 23
2 20
3 30
3 40
我想要的是显示按ID分组的数据,显示每个产品的售价。
我的期望是这样的:
id priceA PriceB PriceC
1 23 NULL NULL
2 14 23 20
3 30 40 NULL
答案 0 :(得分:1)
这不是正确的做事方式 你应该使用一个单独的表并尝试一些主键。
假设您有一个包含ID和价格的poductprice表 提出像
这样的观点 CREATE VIEW history AS (
SELECT
id,
CASE WHEN id = "1" THEN price END AS priceA,
CASE WHEN id = "2" THEN price END AS priceB,
CASE WHEN id = "3" THEN price END AS priceC
FROM productprice
);
SELECT * FROM history;
答案 1 :(得分:1)
这个要求确实不适合SQL,但是可以通过大量涉及“动态sql”和fudges实现相当于row_number()的小工具来实现。即使用CTE和row_number()更容易实现,如果MySQL得到了bith,可以重新访问它。
无论如何,所需要的是将价格变为编号列,因此每个产品的第一个价格在第一列中,第二个价格在第二列中,依此类推。因此,我们首先需要一种对行进行编号的方法,这些行稍后将转换为列。在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表达式与想要的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`
答案 2 :(得分:0)
你可能想要这样的东西:
return {greeting:obj.val1.val2}