2

このコミュニティは初めてです...このリソースが大好きだと言わざるを得ませんが、素晴らしいです。:)

(さらに先に進む前に、複数のクエリを使用し、PHP 配列を使用して取得したものを組み合わせることで、この問題に対する望ましくない機能的な解決策を既に達成していることを指摘したいと思いますが、MySQL と私が持っているものには弱いです私のプロジェクトでは何十もの SQL クエリを使用しており、それらを適切に記述する方法を学びたいと思っています。 )

私は本質的に、UNIONステートメントまたはそれらの行に沿った何かを使用して、2つのほぼ同一のMySQLレコードセットをマージしようとしています。私はこれに対する解決策を見つけようと何年にもわたって探し回ってきましたが、現時点では私には解決できません。それで、ここに私の最初の質問があります:

私のデータ構造は比較的単純ですが、それを使用したい方法はおそらく少し一般的ではないと思います. モバイルデバイスからPHPサーバーに定期的にデータを送信する一連のユーザーがいます。PHPサーバーはデータを処理し、コンテンツをMySQLデータベースに保存します。これは、おそらく少し非正統的なところです。ユーザーは、事実上、閉じたチェーン内のリンクです。常に、すべてのユーザーには、リンクとして機能する別のユーザーが 1 人います。私が好むのは「ターゲット」ですが、ユーザー自身が別のユーザーのターゲットとして機能します。 このモデルは直線的に考えることができます: A は B をターゲットにし、B は C をターゲットにし、C は D をターゲットにし、D は A をターゲットにします。

データは次の 2 つのテーブルに格納されます。

  1. ユーザー: ユーザーに関するデータが含まれます (例: UserID、名前、年齢など... TargetID)
  2. パッケージ: すべてのユーザー更新に関するデータが含まれています (例: UserID、Timestamp など...)

ユーザーからリクエストを受け取ったら、次のことを行います。

  1. 最初に、Packages テーブルから最新の更新を取得し、Users テーブルからユーザーのターゲットに関連する経歴情報を取得します。
  2. 次に、Packages テーブルから最新の更新を取得し、Users テーブルから、ターゲットとしてユーザーを持っている人に関する経歴情報を取得します。

これは少し混乱するかもしれないので、明確にするために: 前述のモデルを使用して、B から要求を受け取った場合、A からの最新のパッケージと C からの最新のパッケージを、関連する経歴情報と共に単一のレコードセットで返す必要があります。 . 私は実際にはBに興味がありません!

この時点で私が達成できた最高のものには、3 つのクエリが含まれます。

  1. 最初に、Users テーブルで User の正しい TargetID を確認します。

    SELECT TargetID FROM Users WHERE Users.UserID = [VALUE SUBMITTED IN USER REQUEST];
    
  2. 両方のテーブルをクエリして結果 1 を生成します。

    SELECT Users.UserID, Users.Name, Users.TargetID, Packages.Timestamp, Packages.Latitude, Packages.Longitude, Packages.Message FROM Users, Packages WHERE Packages.UserID = Users.UserID AND Users.UserID = [VALUE OBTAINED FROM QUERY 1] ORDER BY Packages.Timestamp DESC LIMIT 0,1;
    
  3. 両方のテーブルをクエリして結果 2 を生成します。

    SELECT Users.UserID, Users.Name, Users.TargetID, Packages.Timestamp, Packages.Latitude, Packages.Longitude, Packages.Message FROM Users, Packages WHERE Packages.UserID = Users.UserID AND Users.TargetID = [VALUE SUBMITTED IN USER REQUEST] ORDER BY Packages.Timestamp DESC LIMIT 0,1;
    

次に、結果 1 と 2 を PHP 配列にマージし、この配列の内容を、リクエストを送信したユーザーに送り返しました。そのような多くの要求が関係する状況では、このアプローチが効率的であり、理想的であるとは信じがたいです。クエリ 2 と 3 は事実上同一であり、WHERE 句内の単純な OR 条件でそれらを組み合わせることができるはずですが、関心のある両方のユーザーのすべてのパッケージを返さない限り、うまく結合できません。または、正確に 1 つのレコードを返し、2 番目のレコードを破棄します (明らかに、時間制約を間違って適用しています)。たとえば、MySQL は、UNION ステートメントと ORDER BY ステートメントを一緒に間違って使用していることがあります。構文を変更しようとするたびに、構文がすべて間違っています。

この時点で私のプロジェクトを見ると、サーバーが他のすべてのサーバーよりも頻繁に実行しなければならない単一の MySQL タスクであるため、現在のソリューションには本当に不満です。この質問がかなり冗長であることは承知していますが、最初に理解できるように、物事を徹底的に説明する方が常に良いと思います. あなたが私に与えることができるガイダンスや指示を前もって感謝します. 乾杯。

4

1 に答える 1

2

私が正しく理解していれば、次のようなものです。

select 
Users.UserID, 
TargetedPackages.UserID as TargetedID,
TargetedPackages.TimeStamp as TargetedTimestamp,
TargeterPackages.UserID as TargeterID,
TargeterPackages.Timestamp as TargetedTimestamp
from 
Users

INNER JOIN Users as Targeted
on Targeted.TargetId = Users.TargetID

INNER JOIN Users as Targeter
on Targeter.TargetId = Users.UserID

LEFT JOIN Packages as TargetedPackages
on Users.TargetID = TargetedPackages.UserID AND TargetedPackages.Timestamp = (SELECT Max(Timestamp) FROM Packages where Packages.UserID = Users.TargetID)

LEFT JOIN Packages as TargeterPackages
on Targeter.UserID = TargeterPackages.UserID AND TargeterPackages.Timestamp = (SELECT Max(Timestamp) FROM Packages where Packages.UserID = Targeter.UserID)

where Users.UserID = 2
于 2012-07-02T23:19:33.650 に答える