2

私はいくつかのテーブルを持っています:

  • テーブルにはproduct、製品のリストがあります。
  • -テーブルには、userユーザーのリストがあります。
  • -テーブルには、groupユーザーのグループがあります。
  • -tableでは、 and (多対多) をgroup_memberリンクしました。groupmember
  • -テーブルでは、and (多対多) をuser_productリンクしましたuserproduct
  • -テーブルでは、and (多対多) をgroup_productリンクしましたgroupproduct

したがって、ユーザーは多くの製品を持つことができ、製品は多くのユーザーを持つことができます。ユーザーは多くのグループのメンバーになることができ、グループは多くのメンバーを持つことができます。グループは多くの製品を持つことができ、製品は多くのグループを持つことができます。つまり、製品はグループとユーザーの両方を持つことができます。

私がデータベースに尋ねたいのは次useruser_productとおりです。ユーザーの名前。」

これは私が思いついたクエリです:

# First get all the products the user has access to via a group.
SELECT product.name,
       user.first_name
FROM product
       INNER JOIN group_product
               ON group_product.product_id = product.product_id
       INNER JOIN group
               ON group.group_id = group_product.group_id
       INNER JOIN group_member
               ON group_member.group_id = group.group_id
       INNER JOIN user
               ON user.user_id = group_member.user_id
WHERE user.user_id = 1

UNION 

# Now get all the products via direct access from user_product.
SELECT product.name,
       user.first_name
FROM product
       INNER JOIN user_product
               ON user_product.product_id = product.product_id
       INNER JOIN user
               ON user.user_id = user_product.user_id
WHERE user.user_id = 1

これは良いクエリですか、それともこれを JOIN のみのクエリに書き直す方が良い/可能ですか? 100,000 人のユーザー、10,000 のグループ、および 100 の製品がある場合、これは高速なクエリでしょうか? これは適切なデータベース設計ですか、それともこのロジックを別の方法で保存する方がよいでしょうか?

(これは私の最初のより複雑なクエリです。)

4

1 に答える 1

2

クエリには、データモデルに対して正しいアプローチがあります。データモデルの「正確さ」は、実際には変更の量と頻度に依存します。ユーザーがグループに追加またはグループから削除されるたびに、明示的なユーザーと製品の関係を常に保存することを選択できます。これは非正規化の戦術であり、オーバーヘッドをクエリから更新に移します。通常、パフォーマンスがテストされて不十分でない限り、これらの動きを考慮しないのが最善です。

非常に小さな最適化は、結合が完了するまでユーザーと製品への参加を回避することかもしれません。現在、製品名とユーザーfirst_nameのみを選択していますが、多くの列を選択した場合、並べ替え/区別には厳密に必要な作業よりも多くの作業が必要になるため、次のようになります。

select product.name, user.first_name
from
(
select 
group_product.product_id
from  
group_product
inner join group on group.group_id = group_product.group_id
inner join group_member on group_member.group_id = group.group_id
where group_member.user_id = 1
union
select product_id product.name,
from user_product
where user_product.user_id = 1
) as d
inner join product on product.product_id = d.product_id
inner join user on user.user_id = 1
于 2012-12-27T19:34:34.807 に答える