データベースに多数のテーブルがあり、迅速かつ効率的なクエリの構造化に支援が必要です。これまでに作成したさまざまなクエリでは、結果に一貫性がないか、結果が大きくなっています(必要以上の情報が返されるため、後でPHPを使用して結果を制約する必要があります)。これが背景です。
私たちのデータベースは、シニア住宅業界のリードを処理します。各リードには、販売の履歴を提供するだけでなく、次のフォローアップ日(actionDate)をユーザーに通知する多くのメモ(販売履歴)があります。また、各リードに割り当てることができるさまざまなステータス(つまり、アクティブ、トップ10、入居など)もあります(同時にではありません)。リードのステータスは、販売プロセスを通じたリードの進行の履歴です。リードがいつどのようなステータスであったかを確認できます。
基本の「リード」テーブルでは、各リードに「inquiryID」と呼ばれる主キーがあり、これは自動的にインクリメントされます。このキーは、他のほとんどのテーブルで参照され、「リード」テーブルに関連付けられています。これが「リード」テーブルの構造です。
TABLE: lead (~500 rows)
+-------------------+------------+-------+--------+
| Field | Type | Key | Extra |
+-------------------+------------+-------+--------+
| inquiryID | int(11) | PK | AI |
| communityID | int(3) | | |
| initialDate | date | | |
| inquirySource | tinytext | | |
| inquiryType | tinytext | | |
+-------------------+------------+-------+--------+
別のテーブルのタイトルは「leadNote」です。このテーブルは、各リードの販売ジャーナルを処理します。基本的に、営業担当者は、メモを書いた日付(date)、メモを書いている人(salesCounselor)、メモ自体(note)、リードをフォローアップする人(actionCounselor)、およびフォローアップする日付を入力します。 (actionDate)。
TABLE: leadNote (~15000 rows)
+-------------------+------------+-------+--------+
| Field | Type | Key | Extra |
+-------------------+------------+-------+--------+
| inquiryNoteID | int(11) | PK | AI |
| inquiryID | int(11) | FK | |
| date | date | | |
| salesCounselor | tinytext | | |
| note | text | | |
| actionCounselor | int(5) | | |
+-------------------+------------+-------+--------+
私が参照する最後のテーブルは「leadStatusHistory」というタイトルです。このテーブルは、このリードのステータスの履歴を処理します。リードにはさまざまなステータスがありますが、同時にはできません。リードのステータスがいつであるかを追跡できるようにしたいと考えています。リードには、ステータス(leadStatus)、ステータスが割り当てられた日付(statusDate)、および収集されたデータの中で誰がステータスを割り当てたのか(作成者)があります。
TABLE: leadStatusHistory (~1200 rows)
+-------------------+-------------+-------+--------+
| Field | Type | Key | Extra |
+-------------------+-------------+-------+--------+
| historyID | int(11) | PK | AI |
| inquiryID | int(11) | FK | |
| leadStatus | tintytext | | |
| date | datetime | | |
| communityID | int(3) | | |
| timestamp | timestamp | | |
+-------------------+-------------+-------+--------+
私の目標は、inquiryID、actionCounselor、actionDate、および現在のleadStatusを返すクエリを実行できるようにすることです。前に言ったように、私が試した多くの異なるクエリは、さまざまな結果をもたらしました。このリストを収集する方法は2つあります。1)次の連絡日が今日以下のすべてのリードを見つけます(これは、今日フォローアップする予定のリードのリストです)。2)現在特定のleadStatusに一致するすべてのリードを検索します(つまり、現在「movein」のステータスになっているすべてのリードを検索します。
これは、私が探している情報を取得するためにテーブルを注文する方法です。1)inquiryID、actionCounselor(最後に作成された「leadNote」行または最大の「date」のactionCounselor列の値)、actionDate(最後に作成された「leadNote」行または「date」のactionDate列の値)を検索します「これが最大です)、およびleadStatus(最後に作成された「leadStatusHistory」行のleadStatus列の値または最大の「timestamp」)WHERE actionDate(最後に作成された「leadNote」のactionDate列の値)最大の行または「日付」)は、今日以下です。
2)inquiryID、actionCounselor(最後に作成された「leadNote」行または最大の「date」のactionCounselor列の値)、actionDate(最後に作成された「leadNote」行または「date」のactionDate列の値)を検索します「これが最大です)、およびleadStatus(最後に作成された「leadStatusHistory」行のleadStatus列の値または最大の「timestamp」)WHERE LeadStatus(最後に作成された「leadStatusHistory」行のleadStatus列の値)または、最大の「タイムスタンプ」は「入居」と同じです。
これは、現在および過去のクエリの例と、それらの何が問題になっているのかについての私のコメントです。
クエリ#1:
SELECT
tt.inquiryID,
tt.actionDate,
tt.date,
tt.actionCounselor,
(SELECT
leadstatushistory.leadstatus
FROM
leadstatushistory
WHERE
leadstatushistory.inquiryID = tt.inquiryID AND leadstatushistory.historyID = (SELECT
MAX(leadstatushistory.historyID) as historyID
FROM
leadstatushistory
WHERE
inquiryID = tt.inquiryID)) AS leadStatus
FROM
leadnote tt
INNER JOIN
(SELECT
inquiryID,
MAX(inquiryNoteID) as inquiryNoteID,
MAX(leadnote.actionDate) AS actionDate
FROM
leadnote
GROUP BY inquiryID) groupedtt ON tt.inquiryID = groupedtt.inquiryID AND tt.inquiryNoteID = groupedtt.inquiryNoteID
WHERE
tt.actionDate <= '2012-08-27' AND tt.actionDate != '0000-00-00' AND (SELECT
leadstatushistory.leadstatus
FROM
leadstatushistory
WHERE
leadstatushistory.inquiryID = tt.inquiryID AND leadstatushistory.historyID =
(SELECT
MAX(leadstatushistory.historyID) as historyID
FROM
leadstatushistory
WHERE
inquiryID = tt.inquiryID)) != 'Resident' AND tt.communityID = 4
GROUP BY tt.inquiryID
コメント:必要な列を教えてくれましたが、「actionDate」列に最後に作成されたleadNote行の日付が反映されず、leadStatusが間違っている場合があるという苦情がありました。たとえば、leadStatusHistoryテーブルのmax(historyID)は、必ずしも検索する最新のステータスであるとは限りません。時々、私たちの従業員は戻って、過去のリードの欠落しているleadStatusを埋めます。これにより、新しい自動増分historyIDを持つ新しいleadStatusHistory行が作成されます。この場合、ユーザーが入力した日付が過去の日付であったため、最新の(または最大のhistoryID)には最大の「leadStatusHistory.date」がありません(過去の情報を入力して履歴レコードが正確になるようにします)。過去のメモのleadNoteテーブルにメモを入力する場合とまったく同じ問題が発生します。新しい自動増分inquiryNoteIDは、必ずしも最大の「tt.date」を持つ行と一致するとは限りません。
クエリ#2:
SELECT
maxDate.inquiryID, maxDate.date, maxDate.actionDate, maxDate.actionCounselor
FROM
(SELECT
*
FROM
leadnote
ORDER BY date DESC , type ASC, inquiryNoteID DESC) as maxDate
LEFT JOIN
staff ON maxDate.actionCounselor = staff.staffID
WHERE
maxDate.communityID = 4
GROUP BY inquiryID
コメント:必要な列を教えてくれましたが、すべてのリードの情報も見つかります。これは貴重な時間を浪費し、応答を遅くします。次に、PHPを使用して、actionDateが<=今日で日付が「0000-00-00」ではないリードのみを表示するようにデータを制約するか、leadStatusのリードのみを表示するようにデータを制約します。 「入居」の 繰り返しますが、これは私が探している結果を私に与えますが、それは遅いです。また、サブクエリのクエリ「WHERE date <= [today] AND date!= '0000-00-00'」に追加すると、結果が変更されるため、結果が正確でなくなり、PHPを使用して制約する必要があります。結果は、私が探しているステータスのものだけを示しています。
上記の情報を見ると、探している正確な情報をすばやく見つけることができるように、クエリをより適切に構成する方法について誰かが考えていますか。または、テーブルの構造や関係を変更して、探している結果を得る方法はありますか。助けていただければ幸いです。