简单 SQL 查询以展平一行中的多个属性

Simple SQL query to flatten multiple attributes in a row

我第一次尝试在 Excel 中解决我的问题,但没有简单的解决方法,所以决定在 SQL(在 PostgreSQL/pgAdminIII 上)试一试,我是初学者,以及我没有找到令人满意的解决方案的地方。

我的目标是 "flatten" 一个在单行中包含相似属性的数据集,它们应该有自己的一行。

举例说明。我的数据列出购物袋及其内容如下:

id material color fruit1 fruit2 fruit3 
1  cotton   red   apple  banana cherry
2  paper    blue  apple  cherry
3  plastic  red   banana

我需要为每个水果创建一个新行的 table,因此查询结果应该类似于:

id material color fruit  
1  cotton   red   apple  
1  cotton   red   banana 
1  cotton   red   cherry
2  paper    blue  apple
2  paper    blue  cherry
3  plastic  red   banana

到目前为止,我想出了一个涉及 CASE 的查询,但这只是 return 的第一个匹配项,return 也不是所有需要的行。

SELECT  
  id,
    (CASE 
        WHEN 'apple' IN(fruit1, fruit2, fruit3) THEN 'apple_exh'        
        WHEN 'banana' IN(fruit1, fruit2, fruit3) THEN 'banana_exh'
        WHEN 'cherry' IN(fruit1, fruit2, fruit3) THEN 'cherry_exh'              
        ELSE 'Error'
    END) as "Fruit_Here"
FROM 
  mydb.shopping
WHERE 
 'apple' IN(fruit1, fruit2, fruit3)
 OR
 'banana' IN(fruit1, fruit2, fruit3)
 OR
 'cherry' IN(fruit1, fruit2, fruit3)

ORDER BY id;

Returns

id; fruit_here
1;"apple_exh"
2;"apple_exh"
3;"banana_exh"

如果存在允许 CASE return 所有匹配项 而不仅仅是第一个匹配项的技巧,那就太好了。我当前使用一系列 CASEUNION ALL 的解决方法(请参阅下面的苹果和香蕉示例)有效,但不切实际地乏味,因为我的完整数据包括大约 30 种水果(可能我应该将相同的 "flattening" 应用于蔬菜 tables,最初也是在一行中)。

SELECT  
  id,
    (CASE 
        WHEN 'apple' IN(fruit1, fruit2, fruit3) THEN 'apple_exh'                        
        ELSE 'Error'
    END) as "Fruit_Here"
FROM 
  mydb.shopping
WHERE 
 'apple' IN(fruit1, fruit2, fruit3)

UNION ALL

SELECT  
  id,
    (CASE 
        WHEN 'banana' IN(fruit1, fruit2, fruit3) THEN 'banana_exh'
        ELSE 'Error'
    END) as "Fruit_Here"
FROM 
  mydb.shopping
WHERE 
 'banana' IN(fruit1, fruit2, fruit3)

 UNION ALL

 SELECT  
  id,
    (CASE 
        WHEN 'cherry' IN(fruit1, fruit2, fruit3) THEN 'cherry_exh'
        ELSE 'Error'
    END) as "Fruit_Here"
FROM 
  mydb.shopping
WHERE 
 'cherry' IN(fruit1, fruit2, fruit3)

ORDER BY id, "Fruit_Here";

Returns

id; fruit_here
1;"apple_exh"
1;"banana_exh"
1;"cherry_exh"
2;"apple_exh"
2;"cherry_exh"
3;"banana_exh"

我的问题: 在 SQL 中是否有任何其他明显的方法可以执行此任务,而不必为每种水果重复代码?

您只需要为每列创建一个 select 语句:

select id, material, color, fruit1 from mydb.shopping where fruit1 is not null
union 
select id, material, color, fruit2 from mydb.shopping where fruit2 is not null
union 
select id, material, color, fruit3 from mydb.shopping where fruit3 is not null

我已使用 sql 进行报告,但找不到我的代码。 但这是我在快速搜索时发现的。 Convert Rows to columns using 'Pivot' in SQL Server