1

データベースに多数のテーブルがあり、迅速かつ効率的なクエリの構造化に支援が必要です。これまでに作成したさまざまなクエリでは、結果に一貫性がないか、結果が大きくなっています(必要以上の情報が返されるため、後で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を使用して制約する必要があります。結果は、私が探しているステータスのものだけを示しています。

上記の情報を見ると、探している正確な情報をすばやく見つけることができるように、クエリをより適切に構成する方法について誰かが考えていますか。または、テーブルの構造や関係を変更して、探している結果を得る方法はありますか。助けていただければ幸いです。

4

1 に答える 1

1
  1. 私の目標は、inquiryID、actionCounselor、actionDate、および現在のleadStatusを返すクエリを実行できるようにすることです。

    とテーブルからグループごとの最大値を見つけようとしています。つまり、の各グループ内で最大の日付を持つレコードです。leadNoteleadStatusHistoryinquiryID

    これは、次の行に沿ったクエリで実現できます。

    SELECT inquiryID, actionCounselor, actionDate, leadStatus
    FROM   (
               leadNote NATURAL JOIN (
                 SELECT   inquiryID, MAX(actionDate) AS actionDate
                 FROM     leadNote
                 GROUP BY inquiryID
               ) AS t
            ) JOIN (
               leadStatusHistory NATURAL JOIN (
                 SELECT   inquiryID, MAX(statusDate) AS statusDate
                 FROM     leadStatusHistory
                 GROUP BY inquiryID
               ) AS t
            ) USING (inquiryID)
    

    最高のパフォーマンスを得るにleadNoteは、に複合インデックスがあり、に複合インデックスがある(inquiryID, actionDate)ことを確認する必要がありleadStatusHistoryます(inquiryID, statusDate, leadStatus)

     ALTER TABLE leadNote ADD INDEX (inquiryID, actionDate);
     ALTER TABLE leadStatusHistory ADD INDEX (inquiryID, statusDate, leadStatus);
    
  2. このリストを収集する方法は2つあります。1)次の連絡日が今日以下のすべてのリードを見つけます(これは、今日フォローアップする予定のリードのリストです)。2)現在特定のleadStatusに一致するすべてのリードを検索します(つまり、現在「movein」のステータスになっているすべてのリードを検索します。

    1. 追加WHERE actionDate <= CURRENT_DATE
    2. 追加WHERE leadStatus = 'move in'
于 2012-08-27T17:40:20.190 に答える