私は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 テーブル内のバージョンを更新する必要があることがわかっている場合、実行する更新クエリがさらにいくつかあります。実際にこのセットアップのトレードオフは価値がありますか?
これをよりよく理解するのを手伝ってくれた人に感謝します!!