ColdFusion查询太慢了

Max*_*Boy 3 mysql sql coldfusion

我在cfloop中有查询,这使得进程非常慢.有没有办法让这个查询更快?

<cfquery name="GetCheckRegister" datasource="myDB">
    SELECT * FROM CheckRegister, ExpenseType 
    Where PropertyID=10
    and ExpenseType.ExpenseTypeID=CheckRegister.ExpenseTypeID 
</cfquery>

<CFOUTPUT query=GetCheckRegister>
    <cfquery name="GetVendorName" datasource="myDB"> SELECT * FROM Vendors WHERE VendorID=#VendorID#</cfquery>
    <!--- I use the vendor name here --->

    <cfset local.CreditDate = "" />
  <cfquery name="getTenantTransactionDateFrom" dataSource="myDB">
    Select TenantTransactionDate as fromDate From TenantTransactions
    Where CheckRegisterID = #CheckRegisterID#
    Order By TenantTransactionDate Limit 1
  </cfquery>
  <cfquery name="getTenantTransactionDateTo" dataSource="myDB">
    Select TenantTransactionDate as ToDate From TenantTransactions
    Where CheckRegisterID = #CheckRegisterID#
    Order By TenantTransactionDate desc Limit 1
  </cfquery>
  <cfif getTenantTransactionDateFrom.fromDate neq "" AND getTenantTransactionDateTo.ToDate neq "">
    <cfif getTenantTransactionDateFrom.fromDate eq getTenantTransactionDateTo.ToDate>
      <cfset local.CreditDate = DateFormat(getTenantTransactionDateFrom.fromDate, 'mm/dd/yyyy') />
    <cfelse>
      <cfset local.CreditDate = DateFormat(getTenantTransactionDateFrom.fromDate, 'mm/dd/yyyy') & " - " & DateFormat(getTenantTransactionDateTo.ToDate, 'mm/dd/yyyy') />
    </cfif>
  </cfif>

  <!--- I use the local.CreditDate here  --->

  <!--- Here goes a table with the data --->
</CFOUTPUT>
Run Code Online (Sandbox Code Playgroud)

cfoutput就像一个循环.

Age*_*eax 6

正如其他人所说,你应该摆脱循环并使用连接.查看内部循环,代码检索每个CheckRegisterID的最早和最晚日期.而不是使用LIMIT,使用MIN和MAX以及GROUP BY CheckRegisterID等聚合函数.然后将该结果包装在派生查询中,以便将结果连接回CheckRegister ON id.

原始查询中的某些列没有作用域,所以我做了一些猜测.还有改进的余地,但类似的东西足以让你开始.

-- select only needed columns
SELECT cr.CheckRegisterID, ... other columns
FROM CheckRegister cr 
       INNER JOIN ExpenseType ex ON ex.ExpenseTypeID=cr.ExpenseTypeID 
       INNER JOIN Vendors v ON v.VendorID = cr.VendorID
       LEFT JOIN 
       (
            SELECT CheckRegisterID
              , MIN(TenantTransactionDate) AS MinDate
              , MAX(TenantTransactionDate) AS MaxDate
            FROM  TenantTransactions
            GROUP BY CheckRegisterID
       ) tt ON tt.CheckRegisterID = cr.CheckRegisterID

WHERE cr.PropertyID = 10
Run Code Online (Sandbox Code Playgroud)

我强烈建议阅读JOIN,因为它们对任何网络应用程序IMO都至关重要.


Sha*_*awn 5

您应该在一个查询中获取所有数据,然后使用该数据输出您想要的内容.与数据库的多个连接几乎总是比在一次旅行中获取数据并使用它更加耗费资源.要获得结果:

SQL小提琴

初始架构设置:

CREATE TABLE CheckRegister ( checkRegisterID int, PropertyID int, VendorID int, ExpenseTypeID int ) ;
CREATE TABLE ExpenseType ( ExpenseTypeID int ) ;
CREATE TABLE Vendors ( VendorID int ) ;
CREATE TABLE TenantTransactions ( checkRegisterID int, TenantTransactionDate date, note varchar(20) );

INSERT INTO CheckRegister ( checkRegisterID, PropertyID, VendorID, ExpenseTypeID )
VALUES (1,10,1,1),(1,10,1,1),(1,10,2,1),(1,10,1,2),(1,5,1,1),(2,10,1,1),(2,5,1,1) 
;

INSERT INTO ExpenseType ( ExpenseTypeID ) VALUES (1), (2) ;
INSERT INTO Vendors ( VendorID ) VALUES (1), (2) ;

INSERT INTO TenantTransactions ( checkRegisterID, TenantTransactionDate, note )
VALUES 
    (1,'2018-01-01','start')
  , (1,'2018-01-02','another')
  , (1,'2018-01-03','another')
  , (1,'2018-01-04','stop')
  , (2,'2017-01-01','start')
  , (2,'2017-01-02','another')
  , (2,'2017-01-03','another')
  , (2,'2017-01-04','stop')
 ;
Run Code Online (Sandbox Code Playgroud)

主要查询:

SELECT cr.*
  , max(tt.TenantTransactionDate) AS startDate
  , min(tt.TenantTransactionDate) AS endDate
FROM CheckRegister cr 
INNER JOIN ExpenseType et ON cr.ExpenseTypeID = et.ExpenseTypeID
INNER JOIN Vendors v ON cr.vendorID = v.VendorID 
LEFT OUTER JOIN TenantTransactions tt ON cr.checkRegisterID = tt.CheckRegisterID
WHERE cr.PropertyID = 10
GROUP BY cr.CheckRegisterID, cr.PropertyID, cr.VendorID, cr.ExpenseTypeID
Run Code Online (Sandbox Code Playgroud)

结果:

| checkRegisterID | PropertyID | VendorID | ExpenseTypeID |  startDate |    endDate |
|-----------------|------------|----------|---------------|------------|------------|
|               1 |         10 |        1 |             1 | 2018-01-04 | 2018-01-01 |
|               1 |         10 |        1 |             2 | 2018-01-04 | 2018-01-01 |
|               1 |         10 |        2 |             1 | 2018-01-04 | 2018-01-01 |
|               2 |         10 |        1 |             1 | 2017-01-04 | 2017-01-01 |
Run Code Online (Sandbox Code Playgroud)

我只添加了2个检查寄存器,但CheckRegisterID 1有2个供应商和2个供应商1的费用类型.这看起来像查询中的重复数据.如果您的数据没有以这种方式设置,您将不必在最终查询中担心它.

使用正确的JOIN语法来获取所需的相关数据.然后,您可以聚合该数据以获取fromDatetoDate.如果您的数据更复杂,您可能需要查看窗口函数.https://dev.mysql.com/doc/refman/8.0/en/window-functions.html

我不知道你的最终输出是什么样的,但上面的查询一次性给你所有的查询数据.并且该数据的每一行都应该为您提供输出所需的内容,因此现在您只需要一个查询来循环.