2012-08-27 16 views
1

我在數據庫中有許多表,並且我需要幫助構建快速高效的查詢。通過我迄今爲止編寫的不同查詢,結果可能不一致或較大(返回的信息比我需要的要多,因此必須稍後使用PHP來約束結果)。這是背景。如何構建mySQL查詢以查找按特定順序排序的相關信息

我們的數據庫處理老年住宅行業的線索。每個領導都有許多票據(銷售歷史),不僅給出銷售歷史,而且通知用戶下一個跟進日期(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」。該表處理每個銷售線索的銷售日記帳。基本上,銷售人員會在撰寫票據的日期(銷售人員),票據本身(註釋),跟進主管(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查詢。正如我前面所說,我嘗試過的許多不同的查詢帶來了不同的結果。我想收集這個列表有兩種方式。 1)找到下一個聯繫日期小於或等於今天的所有潛在客戶(這是今天跟進的潛在客戶名單)。 2)找到與當前某個leadStatus相匹配的所有線索(即,查找當前狀態爲「移入」的所有線索。

這就是我如何訂購表格以獲取我的信息查找 1)查找inquiryID,actionCounselor(最近創建的「leadNote」行或「date」最大的actionCounselor列中的值),actionDate(最近創建的「leadNote」的actionDate列中的值)最大的行或「日期」)和leadStatus(最近創建的「leadStatusHistory」行中的leadStatus列中的值或最大的「時間戳」)WHERE actionDate(最近一次的actionDate列中的值創建「leadNote」行或「最大」的日期)小於或等於今天。

2)查找詢問ID,actionCounselor(最近創建的「leadNote」行或「date」最大的actionCounselor列中的值),actionDate(最近創建的「leadNote」的actionDate列中的值)最大的行或「日期」)和leadStatus(最近創建的「leadStatusHistory」行中的leadStatus列中的值或最大的「時間戳」)WHERE leadStatus(最近創建的leadStatus列中的值「leadStatusHistory」行或最大的「時間戳」)等於「移入」。

下面是一些當前和過去的查詢和我的評論的例子,他們有什麼問題。

查詢#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過去的線索。這將創建一個新的leadStatusHistory行,並創建一個新的自動增量historyID。在這種情況下,最近的(或最大的歷史ID)沒有最大的「leadStatusHistory.date」,因爲用戶輸入的日期是過去的日期(填寫過去的信息以便我們的歷史記錄是準確的)。我們在將筆記輸入leadNote表格以查找以前的筆記時也遇到同樣的問題。新的自動增量查詢註釋ID不一定匹配具有最大「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來限制數據,以僅顯示具有< = today的actionDate和不是「0000-00-00」的日期的數據,或者限制數據僅顯示帶leadStatus的數據「移入」。同樣,這確實給了我正在尋找的結果,但速度很慢。此外,如果我在子查詢中添加查詢「WHERE date < = [today] AND date!='0000-00-00'」,它會更改結果以使它們不準確,然後我仍然必須使用PHP來約束結果只顯示那些我正在尋找的狀態。

通過查看上述信息,是否有人有任何想法如何更好地構建我的查詢,以便我可以快速找到我正在尋找的確切信息。或者有沒有辦法改變表格的結構或關係以獲得我期待的結果。請,任何幫助表示讚賞。

+1

您可以發佈一些EXPLAIN輸出嗎? –

+0

您的文本正文中提到了不會出現在您的表結構中的列leadNote.actionDate,leadStatusHistory.statusDate和leadStatusHistory.author。那是一個疏忽?你還應該閱讀關於獲取[groupwise maxima](http://dev.mysql.com/doc/en/example-maximum-column-group-row.html)。 – eggyal

回答

1
  1. 我的目標是能夠運行,返回inquiryID,actionCounselor,actionDate和當前leadStatus查詢。

    您正在尋求找到你的leadNoteleadStatusHistory表的groupwise maxima:即各組的inquiryID內的最大日期的記錄。

    你可以用大意如下的查詢實現這一目標:

    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. 有兩種類型的,我想收集這些列表的方式。 1)找到下一個聯繫日期小於或等於今天的所有潛在客戶(這是今天跟進的潛在客戶名單)。2)找到目前符合特定leadStatus所有線索(即,查找目前與的「移動中」狀態的所有線索。

    1. 添加WHERE actionDate <= CURRENT_DATE
    2. 添加WHERE leadStatus = 'move in'