0

私は6つのテーブルを持っています。これらは、この例では単純化されています。

user_items

ID | user_id | item_name | version
-------------------------------------
1  | 123     | test      | 1

data

ID | name | version | info
----------------------------
1  | test | 1       | info

data_emails

ID | name | version | email_id
------------------------
1  | test | 1       | 1
2  | test | 1       | 2

emails

ID | email
-------------------
1  | email@address.com
2  | second@email.com

data_ips

ID | name | version | ip_id
----------------------------
1  | test | 1       | 1
2  | test | 1       | 2

ips

ID | ip
--------
1  | 1.2.3.4
2  | 2.3.4.5

私が達成しようとしていることは次のとおりです。

ユーザー (123) は、'test' という名前の項目を持っています。これは、特定のエントリに必要な基本情報です。

「data」テーブルにデータがあり、現在のバージョンは 1 であるため、user_items テーブルのバージョンも 1 です。2 つのテーブルは、名前とバージョンによってリンクされています。ユーザーがデータを持っていないアイテムを持つ可能性があるため、セットアップはこのようなものです。同様に、データは持っているがユーザーが所有していないアイテムがある可能性があります

各アイテムには、0 個以上の電子メールと IP が関連付けられています。これらは多くのアイテムで同じである可能性があるため、実際の電子メール varchar を何度も複製するのではなく、email_id/ip_id およびそれぞれの ID 列に基づいて、それぞれ email および ips テーブルにリンクする data_emails および data_ips テーブルを用意します。

電子メールと IP は、アイテム名とバージョン番号を介してデータ バージョンに再度関連付けられます。

私の最初の質問は、これは良い/よく最適化されたデータベース設定ですか?

次のクエリと主な質問は、この複雑なデータ構造を結合することです。

私が持っていたのは:

PHP
- get all the user items
- loop through them and get the most recent data entry (if any)
- if there is one get the respective emails
- get the respective ips

ユーザー アイテムの数に応じて、それは 3 つのクエリまたは本質的に無限にカウントされますか?

上記は非効率的であると思わせられたので、セットアップを 1 つのクエリを使用して同じデータを取得するように凝縮したいと考えました。

次のコードでそれを達成しました

SELECT user_items.name,GROUP_CONCAT( emails.email SEPARATOR ',' ) as emails, x.ip

FROM user_items

JOIN data AS data ON (data.name = user_items.name AND data.version = user_items.version)

LEFT JOIN data_emails AS data_emails ON (data_emails.name = user_items.name AND data_emails.version = user_items.version)

LEFT JOIN emails AS emails ON (data_emails.email_id = emails.ID)

LEFT JOIN
     (SELECT name,version,GROUP_CONCAT( the_ips.ip SEPARATOR ',' ) as ip FROM data_ips
     LEFT JOIN ips as the_ips ON data_ips.ip_id = the_ips.ID  ) 
     x ON (x.name = data.name AND x.version = user_items.version)

私はこの点に到達するためにたくさんの読書を行い、ここにたどり着くためにたゆまぬ努力をしました。これは私が必要とするように機能します-この質問は、代わりにこれを使用する利点は何ですか?

以前は結果を乗算していたので(複雑な結合に基づいていると思います)、ipsを取得するためにサブクエリを使用する必要がありました(私は信じていますか?)。このサブクエリがどのように機能するかは、私の主な混乱だと思います。

質問のまとめ。

-データベースのセットアップは、私の用途に合わせて適切にセットアップされていますか? 改善をいただければ幸いです。また、知識を広げるのに役立つリソースがあれば、それは素晴らしいことです。

-SQL のサブクエリは実際にどのように機能しますか?クエリは何をしているのですか?

-左の結合を使用し続けるのは正しいですか - ユーザー項目を返したいのですが、右に該当する場合は null 値を返します。

-潜在的に無限の数のクエリを 2 に置き換えているのでしょうか? これは本当の違いを生むでしょうか?上記は改善できますか?

- データ テーブル内のアイテムのバージョンを更新するときに、user_items テーブル内のバージョンを更新する必要があることがわかっている場合、実行する更新クエリがさらにいくつかあります。実際にこのセットアップのトレードオフは価値がありますか?

これをよりよく理解するのを手伝ってくれた人に感謝します!!

4

1 に答える 1

0

データ レイアウトと目的を考えると、クエリは正しいです。少量のデータしか取得していない場合、パフォーマンスの問題にはなりません。これは、データ量が増えるとすぐに変化します。ただし、大量のデータがある場合、すべてのデータを一度に表示する必要がある状況はほとんどなく、結果が何らかの方法でフィルター処理されることを意味します。それらがどのようにフィルタリングされるかは、クエリの構造に大きな影響を与えます。

私のSQLのサブクエリは実際にどのように機能しますか

現在、正しく動作しません - GROUP BY はありません

実際にこのセットアップのトレードオフは価値がありますか?

いいえ - スキーマが正規化されすぎていることを意味します。

于 2013-04-09T18:42:34.300 に答える