将记录展平到MySQL中的列中

时间:2018-04-26 18:38:45

标签: mysql sql

我想将表中的多个记录展平为结果集中的不同列。例如:

select product_id, url from images where product_id = 1;

+-------------+-------------------------------+
| product_id  | url                           |
+-------------+-------------------------------+
|           1 | http://example.com/images/abc |
|           1 | http://example.com/images/def |
|           1 | http://example.com/images/ghi |
+-------------+-------------------------------+

我希望结果集有三列如下:

+-------------+---------------------------------+-------------------------------+-------------------------------+
| product_id  | Image 1                         | Image 2                       | Image 3                       | 
+-------------+---------------------------------+-------------------------------+-------------------------------+
|           1 | http://example.com/images/abc   | http://example.com/images/def | http://example.com/images/ghi |
+-------------+---------------------------------+-------------------------------+-------------------------------+

如果我们没有三行,我希望最后一列为null。对于前 -

select product_id, url from images where product_id = 2;
+-------------+-------------------------------+
| product_id  | url                           |
+-------------+-------------------------------+
|           2 | http://example.com/images/abc |
|           2 | http://example.com/images/def |
+-------------+-------------------------------+

然后,输出应为:

+-------------+---------------------------------+-------------------------------+-------------------------------+
| product_id  | Image 1                         | Image 2                       | Image 3                       | 
+-------------+---------------------------------+-------------------------------+-------------------------------+
|           2 | http://example.com/images/abc   | http://example.com/images/def | NULL                          |
+-------------+---------------------------------+-------------------------------+-------------------------------+

如果超过3行,我们可以放心地忽略3行以上。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:1)

相关子查询可能是最简单的方法:

class Parent {
    constructor() {
        this.element = document.createElement('div');
        this.element.setAttribute('class', 'parent');

        // add elements from instances
        this.element.appendChild(new Child(1, this).element);
        this.element.appendChild(new Child(2, this).element);
        this.element.appendChild(new Child(3, this).element);

        // event delegate
        this.element.addEventListener('click', (e) => {
            // would like to get the particular instance of the class "Child" that was clicked
        });
    }

    something(id) {
        console.log('something', id);
    }
}

class Child  {
    constructor(id, parentReference) {
        this.id = id;
        this.element = document.createElement('div');
        this.element.setAttribute('class', 'child');

        // would like to avoid adding a click event for each and use the parent as delegate
        this.element.addEventListener('click', () => {
            parentReference.something(this.id)
        });
    }
}

这假设您有一个名为select p.product_id, (select i.url from images i where i.product_id = p.product_id order by i.image_id limit 1 offset 0 ) as url1, (select i.url from images i where i.product_id = p.product_id order by i.image_id limit 1 offset 1 ) as url2, (select i.url from images i where i.product_id = p.product_id order by i.image_id limit 1 offset 2 ) as url3 from products p; 的表。如果没有,您可以随时使用products

这也假设您在(select distinct product_id from images) p中有一个图片ID列。如果没有,您可以使用images

如果您不想使用order by url表格,可以执行以下操作:

products

答案 1 :(得分:1)

这将按照product_id对url组中的记录进行排序。然后每个group_id得到前三个记录。

select product_id,
       max(case when rank=1 then url end) as url_1,
       max(case when rank=2 then url end) as url_2,
       max(case when rank=3 then url end) as url_3
from (       
  select  a.product_id, 
        a.url,
        count(b.product_id)+1 as rank
  from  images a 
  left join images b 
  on a.product_id=b.product_id and a.url>b.url
  group by  a.product_id,
          a.url
   )  t
group by product_id
order by product_id;

答案 2 :(得分:1)

MySQL非常善于制作应该更加容易的事情。这仍然是一个PIVOT,但它在MySQL中与T-SQL略有不同。

编辑:我们可以使用动态变量ROW_NUMBER()复制@rn功能以保存行号,并@pid保存前一行的product_ID,然后{{1回到CROSS APPLY表。我使用images值来关联rn记录。

product_ID 3表明它会忽略返回的超过3个图片网址。

SQL Fiddle

MySQL 5.6架构设置

Product_ID

查询1

CREATE TABLE images (product_id int, url varchar(50) ) ;
INSERT INTO images 
SELECT 1,'http://example.com/images/abc' UNION ALL
SELECT 1,'http://example.com/images/def' UNION ALL
SELECT 1,'http://example.com/images/ghi' UNION ALL
SELECT 2,'http://example.com/images/abc' UNION ALL
SELECT 2,'http://example.com/images/def' UNION ALL
SELECT 3,'http://example.com/images/qrz' UNION ALL
SELECT 3,'http://example.com/images/rzq' UNION ALL
SELECT 3,'http://example.com/images/zqr' UNION ALL
SELECT 3,'http://example.com/images/qqq' UNION ALL
SELECT 3,'http://example.com/images/rrr' UNION ALL
SELECT 3,'http://example.com/images/zzz'
;

<强> Results

SELECT s1.product_ID
  , max( CASE WHEN s1.rn = 1 THEN s1.url END ) AS Image1
  , max( CASE WHEN s1.rn = 2 THEN s1.url END ) AS Image2
  , max( CASE WHEN s1.rn = 3 THEN s1.url END ) AS Image3
FROM (
  SELECT t1.product_ID, t1.url
    , @rn:=CASE WHEN @pid=product_ID THEN @rn+1 ELSE 1 END AS rn
    , @pid:=product_ID AS pid
  FROM images t1, ( SELECT @rn:=0,@pid:='' ) AS t
  ORDER BY t1.product_ID
) s1
GROUP BY s1.product_ID
ORDER BY s1.product_ID