0

次のテーブルがある場合、「items」テーブルのすべてのアイテムのリストと、「colors」テーブルの各色の列を含むSQLクエリを作成するにはどうすればよいですか。リストされたアイテムごとに、どの色を示しますか。アイテムはと関係があります。

それがまったく不明な場合は、明確にするのに役立つ追加情報を教えてください。テーブル情報と目的の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

ありがとう、コリン

4

4 に答える 4

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
于 2009-09-01T17:07:55.550 に答える
3

オラクル11gを使用していますか?

これは、11gの新しいピボット機能の理想的な使用法のようです。

于 2009-09-01T17:05:42.840 に答える
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句のコードの代わりに色の名前を使用して、(内部)が色テーブルに結合するときにサブクエリを作成します。

于 2009-09-01T17:11:31.283 に答える
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)はできません)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)
)

与える:

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>
于 2011-11-10T13:28:29.710 に答える