鉴于以下表格,我如何构建一个SQL查询,其中包含“items”表中所有项目的列表,以及“colors”表中每种颜色的列,对于列出的每个项目,该项目与哪种颜色有关系。
如果不清楚,请告诉我哪些其他信息有助于澄清。表信息和所需的SQL结果如下:
项目表:
id | item_name
1 | 'item 1'
2 | 'item 2'
3 | 'item 3'
颜色表:
id | color_name
1 | 'red'
2 | 'blue'
3 | 'green'
item_color表:
item_id | color_id
1 | 1
1 | 3
2 | 2
2 | 3
3 | 2
所需的SQL查询结果:
item_name | red | blue | green
'item 1' | 1 | null | 1
'item 2' | null| 1 | 1
'item 3' | null| 1 | null
谢谢, 科林
答案 0 :(得分:5)
使用:
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
如果您想要与项目相关联的红色/蓝色/绿色的总数,请将MAX更改为COUNT。
使用子查询因子替代:
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
答案 1 :(得分:3)
你是在oracle 11g吗?
这似乎是11g新pivot功能的理想用途
答案 2 :(得分:2)
如果你事先知道所有可能的颜色,你可以做得很乱但有效。 如果你事先不知道所有可能的颜色,那就更难了 - 你必须运行一些查询来找出哪些列将出现在结果表中,然后制作SQL来创建那些列(动态SQL)
因此,我们假设您知道结果表中的列:
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
请注意,在此公式中,我在构建查询时使用了 colors 表中的数据。替代形式将子查询构建为颜色表的(内部)连接,使用颜色名称而不是WHERE子句中的代码。
答案 3 :(得分:1)
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;
然后选择:
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')
);
给出:
item 1 1 0 1
item 2 0 1 1
item 3 0 1 0
如果您事先不知道颜色列表,可以先选择颜色表,然后动态构建枢轴选择(不能使用for color_name in (select color_name from color)
这样的子选项)或者您可以使用{{1然后对结果进行后处理:
pivot xml
给出:
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)
)