加入 4 个表并分配默认行
Joining 4 tables and assigning default rows
我有以下 4 个 table:
商店:
id | name
------------------
1 Store 1
2 Store 2
3 Store 3
4 Store 4
5 Store 5
6 Store 6
ITEM_TYPES:
type | description
----------------------
*A *All (Automatically all stores would have this item)
*SP *Store_Specfic (Only a specific store would have this item)
T Toys
H Home
P Pet
STORES_ITEM_TYPES:
STORE_ID | ITEM_TYPE
------------------------
1 T
1 P
3 T
5 T
5 H
5 P
项目:
ITEM_NAME | SPECIFIC_STORE_ID | ITEM_TYPE
--------------------------------------------------------------------
CAT NULL P
BROOM NULL H
LEGO NULL T
BATTERY NULL *A
GIFT CARD NULL *A
PARROT NULL P
STORE2 ONLY ITEM 2 *SP
我想输出每个商店的所有商品:
STORE_NAME | ITEM_NAME | ITEM_TYPE
-------------------------------------------------
STORE1 BATTERY *A
STORE1 GIFT CARD *A
STORE1 LEGO *T
STORE1 CAT *P
STORE1 PARROT *P
STORE2 BATTERY *A
STORE2 GIFT CARD *A
STORE2 STORE2 ONLY ITEM *SP
STORE3 BATTERY *A
STORE3 GIFT CARD *A
STORE3 LEGO *T
STORE4 BATTERY *A
STORE4 GIFT CARD *A
STORE5 BATTERY *A
STORE5 GIFT CARD *A
STORE5 CAT *P
STORE5 PARROT *P
STORE5 BROOM *H
STORE6 BATTERY *A
STORE6 GIFT CARD *A
所以发生了什么事?我有一些商店。我有一些物品。这些项目有一个类型。例如,LEGO
,是一个玩具类型的项目。有些项目具有“特殊”类型。这些以“*”为前缀。 *A
类型代表“全部”。这意味着该商品应该出现在每家商店中。还有一种类型 *SP
表示该商品只能在一个特定的商店中,并且该商店在 ITEMS
table.
中指示
我要查询的是显示每家商店的所有商品。
我面临的问题是 STORES_ITEM_TYPES table 没有指定特殊类型(*A 和 *SP)。这是因为假定这些类型本质上已经是所有商店的一部分,因此不需要指定它们(这不是我的数据模型)。
我尝试了以下查询:
SELECT *
FROM stores p,
stores_item_types t,
items r,
item_types y
WHERE stores.store_id = stores_item_types.store_id
AND stores_item_types.item_type = items.item_type
AND stores_item_types.item_type = item_types.item_type
除了特殊商品(*A 和 *SP),我收到了所有商品。所以我的输出目前是这样的:
STORE_NAME | ITEM_NAME | ITEM_TYPE
-------------------------------------------------
STORE1 LEGO *T
STORE1 CAT *P
STORE1 PARROT *P
STORE3 LEGO *T
STORE5 CAT *P
STORE5 PARROT *P
STORE5 BROOM *H
这是一个 sqlfiddle: sqlfiddle.com/#!9/cae02d/1
注意:此答案的先前版本试图(相当笨拙地)绕过不寻常数据模型的局限性。我认为下面的方法是更好、更清晰的方法。
这里的主要问题是数据没有完全规范化,尤其是关于商店和商品类型之间的关联。我的建议是用两个子查询得到更清晰的版本stores_item_types
和items
,然后做简单的INNER JOIN
s.
让我们从stores_item_types
开始。我们希望派生的 table 明确说明每个商店也带有 *A
类型,并且每个商店也带有 自己的 *SP
类型。例如:
SELECT *
FROM stores_item_types sit
UNION
SELECT store_id, '*A'
FROM stores
UNION
SELECT store_id, CONCAT('*SP', store_id)
FROM stores
会产生这样的结果:
STORE_ID ITEM_TYPE
1 *A
1 *SP1
1 P
1 T
2 *A
2 *SP2
3 *A
3 *SP3
... ...
等等。我们还需要 items
的派生版本,以匹配新类型 *SP1
、*SP2
等
SELECT
item_name,
specific_store_id,
CONCAT(item_type, IFNULL(specific_store_id, '')) item_type
FROM items
最终查询将如下所示:
SELECT
s.name store_name,
i.item_name,
i.item_type
FROM stores s
INNER JOIN (
SELECT *
FROM stores_item_types sit
UNION
SELECT store_id, '*A'
FROM stores
UNION
SELECT store_id, CONCAT('*SP', store_id)
FROM stores ORDER BY store_id, item_type
) sit ON s.store_id = sit.store_id
INNER JOIN (
SELECT
item_name,
specific_store_id,
CONCAT(item_type, IFNULL(specific_store_id, '')) item_type
FROM items
) i ON i.item_type = sit.item_type
ORDER BY s.store_id, sit.item_type
您可以在 this fiddle.
中查看此查询的运行情况
你能看看它是否符合你的期望,
我已经使用 union all 来区分 3 个不同的 item_types
第一个联合: 对于那些我们在 stores_item_types
中匹配项目并排除其他项目的项目,例如 *A
和 *SP
.
第二个联合: 仅 item_type = '*A'
并与所有可用的商店 ID 进行了交叉连接。
第三联合: 仅 item_type='*SP'
并加入商店 ID 以包含到特定商店。
select *
from
(
-- for all matched items in store_item_types
select st.id,st.name,it.item_name,it.item_type
from stores st
join stores_item_types sit
on st.id = sit.store_id
and sit.item_type not in ('*A','*SP')
join items it
on sit.item_type = it.item_type
join item_types ity
on sit.item_type = ity.type
union all
-- item type *A for all stores
select st.id,st.name,it.item_name,it.item_type
from stores st
cross join items it
on it.item_type = '*A'
union all
-- specific items for specific store
select st.id,st.name,it.item_name,it.item_type
from stores st
join items it
on it.specific_store_id = st.id
where it.item_type = '*SP'
) a
order by id,case item_type
when '*A' then 1
when 'H' then 2
when 'P' then 3
when 'T' then 4
when '*SP' then 5
else 6
end;
注意:我为了方便查看输出而添加的额外命令可以删除。而且我只采用了根据预期输出所必需的列,如果需要可以添加其他列。
Db<>fiddle供参考
我有以下 4 个 table:
商店:
id | name
------------------
1 Store 1
2 Store 2
3 Store 3
4 Store 4
5 Store 5
6 Store 6
ITEM_TYPES:
type | description
----------------------
*A *All (Automatically all stores would have this item)
*SP *Store_Specfic (Only a specific store would have this item)
T Toys
H Home
P Pet
STORES_ITEM_TYPES:
STORE_ID | ITEM_TYPE
------------------------
1 T
1 P
3 T
5 T
5 H
5 P
项目:
ITEM_NAME | SPECIFIC_STORE_ID | ITEM_TYPE
--------------------------------------------------------------------
CAT NULL P
BROOM NULL H
LEGO NULL T
BATTERY NULL *A
GIFT CARD NULL *A
PARROT NULL P
STORE2 ONLY ITEM 2 *SP
我想输出每个商店的所有商品:
STORE_NAME | ITEM_NAME | ITEM_TYPE
-------------------------------------------------
STORE1 BATTERY *A
STORE1 GIFT CARD *A
STORE1 LEGO *T
STORE1 CAT *P
STORE1 PARROT *P
STORE2 BATTERY *A
STORE2 GIFT CARD *A
STORE2 STORE2 ONLY ITEM *SP
STORE3 BATTERY *A
STORE3 GIFT CARD *A
STORE3 LEGO *T
STORE4 BATTERY *A
STORE4 GIFT CARD *A
STORE5 BATTERY *A
STORE5 GIFT CARD *A
STORE5 CAT *P
STORE5 PARROT *P
STORE5 BROOM *H
STORE6 BATTERY *A
STORE6 GIFT CARD *A
所以发生了什么事?我有一些商店。我有一些物品。这些项目有一个类型。例如,LEGO
,是一个玩具类型的项目。有些项目具有“特殊”类型。这些以“*”为前缀。 *A
类型代表“全部”。这意味着该商品应该出现在每家商店中。还有一种类型 *SP
表示该商品只能在一个特定的商店中,并且该商店在 ITEMS
table.
我要查询的是显示每家商店的所有商品。
我面临的问题是 STORES_ITEM_TYPES table 没有指定特殊类型(*A 和 *SP)。这是因为假定这些类型本质上已经是所有商店的一部分,因此不需要指定它们(这不是我的数据模型)。
我尝试了以下查询:
SELECT *
FROM stores p,
stores_item_types t,
items r,
item_types y
WHERE stores.store_id = stores_item_types.store_id
AND stores_item_types.item_type = items.item_type
AND stores_item_types.item_type = item_types.item_type
除了特殊商品(*A 和 *SP),我收到了所有商品。所以我的输出目前是这样的:
STORE_NAME | ITEM_NAME | ITEM_TYPE
-------------------------------------------------
STORE1 LEGO *T
STORE1 CAT *P
STORE1 PARROT *P
STORE3 LEGO *T
STORE5 CAT *P
STORE5 PARROT *P
STORE5 BROOM *H
这是一个 sqlfiddle: sqlfiddle.com/#!9/cae02d/1
注意:此答案的先前版本试图(相当笨拙地)绕过不寻常数据模型的局限性。我认为下面的方法是更好、更清晰的方法。
这里的主要问题是数据没有完全规范化,尤其是关于商店和商品类型之间的关联。我的建议是用两个子查询得到更清晰的版本stores_item_types
和items
,然后做简单的INNER JOIN
s.
让我们从stores_item_types
开始。我们希望派生的 table 明确说明每个商店也带有 *A
类型,并且每个商店也带有 自己的 *SP
类型。例如:
SELECT *
FROM stores_item_types sit
UNION
SELECT store_id, '*A'
FROM stores
UNION
SELECT store_id, CONCAT('*SP', store_id)
FROM stores
会产生这样的结果:
STORE_ID ITEM_TYPE
1 *A
1 *SP1
1 P
1 T
2 *A
2 *SP2
3 *A
3 *SP3
... ...
等等。我们还需要 items
的派生版本,以匹配新类型 *SP1
、*SP2
等
SELECT
item_name,
specific_store_id,
CONCAT(item_type, IFNULL(specific_store_id, '')) item_type
FROM items
最终查询将如下所示:
SELECT
s.name store_name,
i.item_name,
i.item_type
FROM stores s
INNER JOIN (
SELECT *
FROM stores_item_types sit
UNION
SELECT store_id, '*A'
FROM stores
UNION
SELECT store_id, CONCAT('*SP', store_id)
FROM stores ORDER BY store_id, item_type
) sit ON s.store_id = sit.store_id
INNER JOIN (
SELECT
item_name,
specific_store_id,
CONCAT(item_type, IFNULL(specific_store_id, '')) item_type
FROM items
) i ON i.item_type = sit.item_type
ORDER BY s.store_id, sit.item_type
您可以在 this fiddle.
中查看此查询的运行情况你能看看它是否符合你的期望,
我已经使用 union all 来区分 3 个不同的 item_types
第一个联合: 对于那些我们在 stores_item_types
中匹配项目并排除其他项目的项目,例如 *A
和 *SP
.
第二个联合: 仅 item_type = '*A'
并与所有可用的商店 ID 进行了交叉连接。
第三联合: 仅 item_type='*SP'
并加入商店 ID 以包含到特定商店。
select *
from
(
-- for all matched items in store_item_types
select st.id,st.name,it.item_name,it.item_type
from stores st
join stores_item_types sit
on st.id = sit.store_id
and sit.item_type not in ('*A','*SP')
join items it
on sit.item_type = it.item_type
join item_types ity
on sit.item_type = ity.type
union all
-- item type *A for all stores
select st.id,st.name,it.item_name,it.item_type
from stores st
cross join items it
on it.item_type = '*A'
union all
-- specific items for specific store
select st.id,st.name,it.item_name,it.item_type
from stores st
join items it
on it.specific_store_id = st.id
where it.item_type = '*SP'
) a
order by id,case item_type
when '*A' then 1
when 'H' then 2
when 'P' then 3
when 'T' then 4
when '*SP' then 5
else 6
end;
注意:我为了方便查看输出而添加的额外命令可以删除。而且我只采用了根据预期输出所必需的列,如果需要可以添加其他列。
Db<>fiddle供参考