Свести записи в столбцы в MySQL - PullRequest
0 голосов
/ 26 апреля 2018

Я хочу сгладить несколько записей из таблицы как отдельные столбцы в наборе результатов. Например:

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 |
+-------------+---------------------------------+-------------------------------+-------------------------------+

В случае, если у нас нет трех строк, я хочу, чтобы последние столбцы были нулевыми. Для бывших

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 голосов
/ 26 апреля 2018

Это позволит отсортировать записи в группе 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;
0 голосов
/ 26 апреля 2018

MySQL довольно хорош в создании вещей, которые должны быть намного сложнее. Это все еще PIVOT, но в MySQL он немного отличается от T-SQL.

РЕДАКТИРОВАТЬ: Мы можем реплицировать функциональность ROW_NUMBER() с динамическими переменными @rn для хранения номера строки и @pid для хранения product_ID предыдущей строки, затем CROSS APPLY, что обратно в таблицу images. Я использую значение rn для сопоставления записей product_ID.

Product_ID 3 демонстрирует, что будет игнорировать более 3 возвращенных URL-адресов изображений.

SQL Fiddle

Настройка схемы MySQL 5.6 :

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'
;

Запрос 1 :

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

Результаты

| product_ID |                        Image1 |                        Image2 |                        Image3 |
|------------|-------------------------------|-------------------------------|-------------------------------|
|          1 | http://example.com/images/abc | http://example.com/images/def | http://example.com/images/ghi |
|          2 | http://example.com/images/abc | http://example.com/images/def |                        (null) |
|          3 | http://example.com/images/rrr | http://example.com/images/qqq | http://example.com/images/zqr |
0 голосов
/ 26 апреля 2018

Коррелированный подзапрос может быть самым простым подходом:

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.

Это также предполагает, что у вас есть столбец идентификатора изображения в images. Если нет, вы можете использовать order by url.

Если вы не хотите использовать таблицу products, вы можете сделать:

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 (select distinct product_id from images) p;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...