Pregunta

Dadas las siguientes tablas, cómo podría yo crear una consulta SQL que incluye una lista de todos los artículos de los "elementos" de mesa, y una columna para cada color de la tabla "colores" que, para cada elemento de la lista, indica qué colores el artículo tiene una relación con.

Si eso está claro en absoluto, por favor hágamelo saber qué información adicional ayudará a aclarar. La información de la tabla y el resultado deseado SQL son a continuación:

artículos tabla:

id | item_name
1  | 'item 1'
2  | 'item 2'
3  | 'item 3'

tabla colores:

id | color_name
1  | 'red'
2  | 'blue'
3  | 'green'

tabla item_color:

item_id | color_id
1       | 1
1       | 3
2       | 2
2       | 3
3       | 2

deseado resultado de la consulta SQL:

item_name | red | blue | green
'item 1'  |  1  | null |   1
'item 2'  | null|   1  |   1
'item 3'  | null|   1  | null

Gracias, Colin

¿Fue útil?

Solución

Uso:

SELECT item_name,
       MAX(red) 'red',
       MAX(blue) 'blue',
       MAX(green) 'green'
  FROM (SELECT t.item_name,
         CASE
           WHEN c.color_name = 'red' THEN
             1
           ELSE
             NULL
         END 'red',
         CASE
           WHEN c.color_name = 'blue' THEN
             1
           ELSE
             NULL
         END 'blue',
         CASE
           WHEN c.color_name = 'green' THEN
             1
           ELSE
             NULL
         END 'green'       
    FROM ITEMS t
    JOIN ITEM_COLOR ic ON ic.item_id = t.item_id
    JOIN COLORS c ON c.id = ic.color_id)
GROUP BY item_name 

Cambiar MAX cuente si desea que el # total de rojo / azul / verde asociado a un elemento.

alternativo usando Subconsulta Factoring:

WITH icolors AS (
   SELECT t.item_name,
          CASE
           WHEN c.color_name = 'red' THEN
             1
           ELSE
             NULL
         END 'red',
     CASE
       WHEN c.color_name = 'blue' THEN
         1
       ELSE
         NULL
     END 'blue',
     CASE
       WHEN c.color_name = 'green' THEN
         1
       ELSE
             NULL
     END 'green'       
    FROM ITEMS t
    JOIN ITEM_COLOR ic ON ic.item_id = t.item_id
    JOIN COLORS c ON c.id = ic.color_id)
  SELECT t.item_name,
         MAX(t.red) 'red',
         MAX(t.blue) 'blue',
         MAX(t.green) 'green'
    FROM icolors t
GROUP BY t.item_name

Otros consejos

¿Está usted en Oracle 11g?

Esto parece ser un uso ideal para el nuevo característica de pivote en 11g

Si usted sabe todos los colores posibles de antelación, puede hacerlo desordenadamente pero con eficacia. Si usted no sabe todos los colores posibles de antelación, es mucho más difícil - que tiene que ejecutar algunas consultas para averiguar qué columnas aparecerán en la tabla de resultados, y luego elaborar el código SQL para crear las columnas (SQL dinámico) .

Por lo tanto, vamos a suponer que usted sabe las columnas en la tabla de resultados:

SELECT i.item_name, r.red, b.blue, g.green
  FROM items i
       LEFT JOIN
       (SELECT item_name, COUNT(*) AS red
          FROM item_color
         WHERE color_id = 1
         GROUP BY item_name) AS r
       ON i.item_name = r.item_name
       LEFT JOIN
       (SELECT item_name, COUNT(*) AS green
          FROM item_color
         WHERE color_id = 3
         GROUP BY item_name) AS g
       ON i.item_name = g.item_name
       LEFT JOIN
       (SELECT item_name, COUNT(*) AS blue
          FROM item_color
         WHERE color_id = 2
         GROUP BY item_name) AS b
       ON i.item_name = b.item_name

Tenga en cuenta que en esta formulación, he utilizado los datos de los colores Mesa en la construcción de la consulta. Y la forma alternativa sería construir las sub-consultas como (interior) se une a la tabla de colores, usando el nombre del color en lugar del código en las cláusulas WHERE.

create table item (id number not null, item_name varchar2(200) not null);
create table color (id number not null, color_name varchar2(200) not null);
create table item_color (item_id number not null, color_id number not null);

insert into item values (1, 'item 1');
insert into item values (2, 'item 2');
insert into item values (3, 'item 3');


insert into color values (1, 'red');
insert into color values (2, 'blue');
insert into color values (3, 'green');

insert into item_color values (1, 1);
insert into item_color values (1, 3);
insert into item_color values (2, 2);
insert into item_color values (2, 3);
insert into item_color values (3, 2);

commit;

a continuación, seleccione:

select * from
(
select
  i.item_name
  , c.color_name
from
  item i
  , color c
  , item_color ic
where
  ic.item_id = i.id
  and ic.color_id = c.id
) pivot (
  count(color_name) cnt
  for color_name in ('red', 'blue', 'green')
);

da:

item 1    1    0    1
item 2    0    1    1
item 3    0    1    0

en caso de que no conoce la lista de colores de antemano puede seleccionar la tabla de colores primero y luego construir el pivote selecciona dinámicamente (como una subselección for color_name in (select color_name from color) no es posible) o, alternativamente, se puede utilizar pivot xml y postproceso el resultado:

select * from
(
select
  i.item_name
  , c.color_name
from
  item i
  , color c
  , item_color ic
where
  ic.item_id = i.id
  and ic.color_id = c.id
) pivot xml (
  count(color_name) cnt
  for color_name in (any)
)

da:

item 1  <PivotSet><item><column name = "COLOR_NAME">green</column><column name = "CNT">1</column></item><item><column name = "COLOR_NAME">red</column><column name = "CNT">1</column></item></PivotSet>
item 2  <PivotSet><item><column name = "COLOR_NAME">blue</column><column name = "CNT">1</column></item><item><column name = "COLOR_NAME">green</column><column name = "CNT">1</column></item></PivotSet>
item 3  <PivotSet><item><column name = "COLOR_NAME">blue</column><column name = "CNT">1</column></item></PivotSet>
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top