匹配多个属性

时间:2015-04-04 02:52:04

标签: sql

我有3家杂货店,出售(可能)不同的水果。我想知道哪些商店出售相同的水果和水果是什么 我的表是:

ID | Fruit1  | Fruit2   | Fruit3   | Fruit4
---+---------+----------+----------+--------------
1  | apples  | bananas  |          |
2  | apples  | oranges  | cherries | lychees
3  | bananas | cherries | lychees  | 

所以我的输出应如下所示:

ID1 | ID2 | Fruit
----+-----+--------
1   | 2   | apples
1   | 3   | bananas    
2   | 3   | cherries
2   | 3   | lychees

2 个答案:

答案 0 :(得分:1)

您的架构不适合关系数据库。关系数据库没有列表,它们有关系。如果你想要一件东西(一家商店)有很多东西(水果)你就不会制作很多专栏,you make lots of rows。包裹你的头脑有点奇怪。

您的架构应该是这样的。我正在使用MySQL语法。

CREATE TABLE stores (
    id   INTEGER PRIMARY KEY AUTO_INCREMENT,
    name TEXT
);

CREATE TABLE fruit_sold (
    store_id INTEGER REFERENCES stores(id),
    fruit    TEXT
);

对于商店销售的每种水果,它都会在fruit_sold中排成一排。您的数据看起来像这样......

INSERT INTO stores (name)
VALUES ("Fruit Stand"), ("The Pits"), ("Fruit R U");

SELECT * FROM stores;
+----+-------------+
| id | name        |
+----+-------------+
|  1 | Fruit Stand |
|  2 | The Pits    |
|  3 | Fruit R U   |
+----+-------------+

INSERT INTO fruit_sold (store_id, fruit)
VALUES (1, "apples"), (1, "bananas");
INSERT INTO fruit_sold (store_id, fruit)
VALUES (2, "apples"), (2, "oranges"), (2, "cherries"), (2, "lychees");
INSERT INTO fruit_sold (store_id, fruit)
VALUES (3, "bananas"), (3, "cherries"), (3, "lychees");

SELECT * FROM fruit_sold;
+----------+----------+
| store_id | fruit    |
+----------+----------+
|        1 | apples   |
|        1 | bananas  |
|        2 | apples   |
|        2 | oranges  |
|        2 | cherries |
|        2 | lychees  |
|        3 | bananas  |
|        3 | cherries |
|        3 | lychees  |
+----------+----------+

要获取商店名称及其销售的成果,请执行join

SELECT s.name, f.fruit
FROM stores s
JOIN fruit_sold f ON s.id = f.store_id;
+-------------+----------+
| name        | fruit    |
+-------------+----------+
| Fruit Stand | apples   |
| Fruit Stand | bananas  |
| The Pits    | apples   |
| The Pits    | oranges  |
| The Pits    | cherries |
| The Pits    | lychees  |
| Fruit R U   | bananas  |
| Fruit R U   | cherries |
| Fruit R U   | lychees  |
+-------------+----------+

同样,您在SQL中使用行中的列表,而不是列。要获得销售相同水果的所有商店,只需先按水果订购清单,然后按商店名称订购。

SELECT s.name, f.fruit
FROM stores s
JOIN fruit_sold f ON s.id = f.store_id
ORDER BY fruit, s.name;
+-------------+----------+
| name        | fruit    |
+-------------+----------+
| Fruit Stand | apples   |
| The Pits    | apples   |
| Fruit R U   | bananas  |
| Fruit Stand | bananas  |
| Fruit R U   | cherries |
| The Pits    | cherries |
| Fruit R U   | lychees  |
| The Pits    | lychees  |
| The Pits    | oranges  |
+-------------+----------+

但是你只想要卖同样水果的商店。为此,您需要将表与自身进行比较。那是self join。您可以通过在ID不相等的现有表上添加联接来进行自联接。 JOIN fruit_sold f2 ON f.store_id <> f2.store_id。然后,您可以使用WHERE f.fruit = f2.fruit检查销售相同水果的商店。

SELECT s.name, f.fruit
FROM stores s
JOIN fruit_sold f ON s.id = f.store_id
JOIN fruit_sold f2 ON f.store_id <> f2.store_id
WHERE f.fruit = f2.fruit
ORDER BY f.fruit, s.name;
+-------------+----------+
| name        | fruit    |
+-------------+----------+
| Fruit Stand | apples   |
| The Pits    | apples   |
| Fruit R U   | bananas  |
| Fruit Stand | bananas  |
| Fruit R U   | cherries |
| The Pits    | cherries |
| Fruit R U   | lychees  |
| The Pits    | lychees  |
+-------------+----------+

某些数据库有列表,例如Postgres。你不应该依赖它,应该学习适当的关系设计。或者使用具有大多数人期望的正常数据结构的NoSQL database

答案 1 :(得分:0)

  

我在 SQL Server TSQL 中添加了答案;根据标签没有指定或......:

我认为您需要按照特殊ID列出所有水果,所以我使用Union All作为该列表 现在,您需要通过创建新的View或使用With语句来使用该列表,我选择With语句。
我可以建议您使用ID1 < ID2加入时Fruit1 = Fruit2的特殊过滤器使用加入的最简单方法:

with All_Sales (Id, Fruit) 
As (
select Id, Fruit1 as Fruit from Sales where not Fruit1 is null
union All
select Id, Fruit2 as Fruit from Sales where not Fruit2 is null
union all 
select Id, Fruit3 as Fruit from Sales where not Fruit3 is null
union all 
select Id, Fruit4 as Fruit from Sales where not Fruit4 is null
)

select as1.Id as Id1, as2.Id as Id2, as1.Fruit 
from All_Sales as as1 inner join All_Sales as as2 on as1.Fruit = as2.fruit And as1.Id < as2.Id