将通用类别扩展为特定项目

时间:2016-10-12 15:24:12

标签: sql sql-server tsql

我有一个颜色列表(红色,绿色,蓝色),尺寸列表(S,M,L),以及一些输入,如下所示:

| item | color | size  | price |
--------------------------------
| 1    | red   | S     | $10   |
| 1    | other | S     | $8    |
| 2    | all   | all   | $20   |
| 3    | green | S     | $14   |
| 3    | green | other | $16   |

我想要做的是扩展"其他"和#34;所有"行,所以我最终为每种颜色和大小添加一行:

| item | color | size  | price |
--------------------------------
| 1    | red   | S     | $10   |
| 1    | green | S     | $8    |
| 1    | blue  | S     | $8    |
| 2    | red   | S     | $20   |
| 2    | red   | M     | $20   |
| 2    | red   | L     | $20   |
| 2    | green | S     | $20   |
| 2    | green | M     | $20   |
| 2    | green | L     | $20   |
| 2    | blue  | S     | $20   |
| 2    | blue  | M     | $20   |
| 2    | blue  | L     | $20   |
| 3    | green | S     | $14   |
| 3    | green | M     | $16   |
| 3    | green | L     | $16   |

下面的代码为我提供了颜色列的所需结果:

创建脚本:

DECLARE @inputs TABLE 
(
    item    int
   ,color   varchar (10)
   ,size    varchar (10)
   ,price   float
);

insert into @inputs
values
(1, 'red', 'S', 10),
(1, 'other', 'S', 8),
(2, 'all', 'all', 20),
(3, 'green', 'S', 14),
(3, 'green', 'other', 16);

DECLARE @colors TABLE
(
    color   varchar (10)
);

insert into @colors
values
('red'),
('green'),
('blue');

DECLARE @sizes TABLE
(
    size   varchar (10)
);

insert into @sizes
values
('S'),
('M'),
('L');

选择陈述:

/* select rows with specific colors */
SELECT i.item
      ,i.color
      ,i.size
      ,i.price
  FROM @inputs i
 WHERE EXISTS (SELECT 1 
                 FROM @colors c 
                WHERE i.color = c.color
              )
--
UNION ALL
--
/* select rows for all other colors */
    SELECT i.item
          ,c.color
          ,i.size
          ,i.price
      FROM @inputs i
CROSS JOIN @colors c
     WHERE i.color IN ('all', 'other')
       AND NOT EXISTS (SELECT 1 
                         FROM @inputs i2 
                        WHERE c.color = i2.color 
                          AND i.item = i2.item
                          AND i.size = i2.size
                      )

但是我在努力将相同的逻辑应用于size列而不重复上面的代码(因为我必须联合"实际大小"以及" all / other&# 34;基于结果的部分)。什么是解决这个问题的最好方法?

2 个答案:

答案 0 :(得分:1)

您应该能够通过OUTER APPLY子句获得您要查找的结果。以下示例演示:

DECLARE @inputs TABLE 
(
    item    int
   ,color   varchar (10)
   ,size    varchar (10)
   ,price   float
);

insert into @inputs
values
(1, 'red', 'S', 10),
(1, 'other', 'S', 8),
(2, 'all', 'all', 20),
(3, 'green', 'S', 14),
(3, 'green', 'other', 16);

DECLARE @colors TABLE
(
    color   varchar (10)
);

insert into @colors
values
('red'),
('green'),
('blue');

DECLARE @sizes TABLE
(
    size   varchar (10)
);

insert into @sizes
values
('S'),
('M'),
('L');


SELECT       I.item  
            ,(
                CASE I.color 
                    WHEN 'all' THEN CA.color
                    WHEN 'other' THEN CA.color
                    ELSE I.color 
                END
             ) AS color
            ,(
                CASE I.size 
                    WHEN 'all' THEN SA.size
                    WHEN 'other' THEN SA.size
                    ELSE I.size 
                END
             ) AS size
            ,price
FROM        @inputs I
OUTER APPLY (
                SELECT  color
                FROM    @colors colors
                WHERE   (I.color = 'all' OR I.color = 'other') AND colors.color NOT IN (SELECT color from @inputs where item = I.item)
            ) CA
OUTER APPLY (
                SELECT  size
                FROM    @sizes sizes
                WHERE   (I.size = 'all' OR I.size = 'other') AND sizes.size NOT IN (SELECT size from @inputs where item = I.item)
            ) SA

答案 1 :(得分:0)

正如我评论的那样,您的样本数据可能存在错误。但是,这应该是一个简单的解决方案:

select a.item
  ,case when a.color in ('all','other') then b.color
  ,case when a.size a.size in ('all','other') then b.size
  ,a.price from inputs a 
left join colors b on a.color in ('all','other')
left join sizes b on a.size in ('all','other')