仅在一行中显示具有相同ID的所有记录。

时间:2016-11-01 03:38:59

标签: mysql sql

假设我有一张产品价格历史表,这是价格和产品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     

3 个答案:

答案 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}