1

我的数据库中有许多表,我需要帮助来构建快速高效的查询。到目前为止,对于我编写的不同查询,结果要么不一致,要么太大(返回的信息比我需要的多,因此必须稍后使用 PHP 来约束结果)。这是背景。

我们的数据库处理老年住房行业的潜在客户。每个潜在客户都有许多注释(销售历史记录),它们不仅提供销售历史记录,而且通知用户下一个跟进日期(actionDate)。还有许多不同的状态(即,活跃、前 10 名、进入等)每个潜在客户可以分配到(尽管不是同时)。潜在客户的状态是潜在客户在整个销售过程中的发展历史。我们可以看到潜在客户的状态和时间。

在基本“潜在客户”表中,每个潜在客户都有一个名为“inquiryID”的主键,它会自动递增。在大多数其他表中都引用了此键,以将它们与“lead”表相关联。这是“lead”表的结构。

TABLE: lead (~500 rows)
+-------------------+------------+-------+--------+
|  Field            |  Type      |  Key  | Extra  |
+-------------------+------------+-------+--------+
|  inquiryID        |  int(11)   |  PK   |  AI    |
|  communityID      |  int(3)    |       |        |
|  initialDate      |  date      |       |        |  
|  inquirySource    |  tinytext  |       |        |
|  inquiryType      |  tinytext  |       |        |
+-------------------+------------+-------+--------+ 

另一个表的标题是“leadNote”。此表处理每个潜在客户的销售日记帐。基本上,销售人员会输入写笔记的日期(日期)谁正在写笔记(salesCounselor),笔记本身(笔记),谁将跟进潜在客户(actionCounselor),以及他们将跟进的日期(行动日期)。

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”行或“date”上的actionDate列中的值",这是最大的),以及leadStatus(最近创建的“leadStatusHistory”行上的leadStatus列中的值或最大的“timestamp”)WHERE actionDate(最近创建的“leadNote”上的actionDate列中的值最大的行或“日期”)小于或等于今天。

2)查找inquiryID,actionCounselor(最近创建的“leadNote”行或“date”上的actionCounselor列中的值最大),actionDate(最近创建的“leadNote”行或“date”的actionDate列中的值",这是最大的)和leadStatus(最近创建的“leadStatusHistory”行上的leadStatus列中的值或最大的“时间戳”) 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) 不一定是我们想要查找的最新状态。有时我们的员工会回过头来为过去的潜在客户填写缺失的潜在客户状态。这将创建一个新的leadStatusHistory 行,其中包含一个新的自动增量historyID。在这种情况下,最近的(或最大的 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. 我想通过两种方式收集此列表。1) 查找下一次联系日期小于或等于今天的所有潜在客户(这是计划在今天跟进的潜在客户列表)。2) 查找当前与某个leadStatus 匹配的所有潜在客户(即,查找当前状态为“移入”的所有潜在客户。

    1. 添加WHERE actionDate <= CURRENT_DATE
    2. 添加WHERE leadStatus = 'move in'
于 2012-08-27T17:40:20.190 回答