ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

mysql – ColdFusion中的查询优化

2019-07-24 11:24:14  阅读:229  来源: 互联网

标签:sql mysql coldfusion


我在ColdFusion中创建了一个代码,用于从Users和UsersTransactions表中加载数据并将其显示在表中.但是,我的查询需要很长时间才能运行.

<!--- This return about 250 records --->
<cfquery name="getUsers" datasource="db">
    Select * From Users Where test = 5
</cfquery>

<!--- Loop to display the Users info --->
<cfloop query="getUsers">
    <cfset SpecialDebit = 0 />
    <cfset TotalDebit = 0 />
    <cfset SpecialCredit = 0 />
    <cfset TotalCredit = 0 />

    <!--- Loop to get Users Balance --->
    <cfquery name="getUsersTransactions" datasource="db">
        SELECT * FROM UsersTransactions , TransactionTypes, ChargeTypes 
        Where UsersTransactions.TransactionTypeID=TransactionTypes.TransactionTypeID 
        AND ChargeTypes.ChargeTypeID=UsersTransactions.ChargeTypeID  
        AND UsersTransactions.UserID=#getUsers.UserID#
    </cfquery>
    <cfloop query="getUsersTransactions">
        <cfif TransactionTypeID EQ "1"> <!--- This means it's a debit --->
            <cfif ChargeTypeID EQ "6"> <!-- This means its a special debit --->
                <cfset SpecialDebit += TransactionAmount />
            <cfelse>
                <cfset TotalDebit += TransactionAmount />
            </cfif>     
        </cfif>
        <cfif TransactionTypeID EQ "2"> <!--- This means it's a credit --->
            <cfif ChargeTypeID EQ "6"> <!-- This means its a special credit --->
                <cfset SpecialCredit += TransactionAmount />
            <cfelse>
                <cfset TotalCredit += TransactionAmount />
            </cfif>
        </cfif>
    </cfloop>
    <cfset UserSpecialBalance = SpecialDebit - SpecialCredit />
    <cfset UserBalance = TotalDebit - TotalCredit />

    <!--- Display User's data in a table with Column Special Balance and User Balance --->
    .
    .
    .

</cfloop>

花费很长时间的是“getUsersTransactions”查询的循环.有没有办法让这些查询运行得更快?

更新:

一个用户的数据样本:

User.UserID = 10

例如,它将在UsersTransactions中有6条记录

             Transaction
#   UserID   TypeID      ChargeTypeID    TransactionAmount
1   10       1           6               25
2   10       1           6               17
3   10       1           1               50
4   10       2           1               12
5   10       2           6               7
6   10       2           6               18

在这种情况下,我有:

> 2“特殊借记”(记录1和2):SpecialDebit = 25 17 = 42
> 1正常借记(记录3):TotalDebit = 50
> 1正常信用(记录4):TotalCredit = 12
> 2特别信用(记录5和6):SpecialCredit = 7 18 = 25

解决方法:

我上面的建议基本上等于抓取查询中所有用户所需的数据,然后输出这些结果而不是循环以重新运行用户的查询.我添加了一个使用查询的插入.

SQL Fiddle

MySQL 5.6架构设置:

CREATE TABLE users ( userid int, name varchar(10), test int ) ;
INSERT INTO users (userid, name, test)
VALUES 
    ( 1, 'Bill', 5 ) 
  , ( 2, 'Tex', 3 )
  , ( 3, 'Rufus', 5 )
  , ( 4, 'SilentBob', 5 )
  , ( 5, 'Jay', 5 )
;

CREATE TABLE UsersTransactions ( UserID int, TransactionTypeID int, ChargeTypeID int, TransactionAmount int ) ;
INSERT INTO UsersTransactions ( UserID, TransactionTypeID, ChargeTypeID, TransactionAmount )
VALUES 
    ( 1, 1, 6, 2 )  /* Special Debit */
  , ( 1, 1, 1, 5 )  /* Normal Debit */
  , ( 2, 1, 6, 20 )
  , ( 2, 1, 1, 20 )
  , ( 3, 1, 6, 30 )
  , ( 3, 1, 1, 30 )
  , ( 1, 2, 6, 5 )  /* Special Credit */
  , ( 1, 2, 1, 5 )  /* Special Credit */
  , ( 2, 2, 6, 20 )
  , ( 2, 2, 1, 20 )
  , ( 3, 2, 6, 20 )
  , ( 3, 2, 1, 20 )
  , ( 5, 1, 1, 500 )  /* Normal Debit */
;

CREATE TABLE TransactionTypes ( TransactionTypeID int, Description varchar(10) ) ;
INSERT INTO TransactionTypes VALUES ( 1, 'Debit' ), ( 2, 'Credit' ) ;

CREATE TABLE ChargeTypes ( ChargeTypeID int, Description varchar(10) ) ;
INSERT INTO ChargeTypes VALUES ( 1, 'Regular' ), ( 6, 'Special' ) ;

初始查询示例:注意:这可以进一步优化.

SELECT u.userid
  , u.name
  , SUM(CASE WHEN ut.TransactionTypeID = 1  AND ut.ChargeTypeID = 1 THEN ut.TransactionAmount END) AS NormalDebit
  , SUM(CASE WHEN ut.TransactionTypeID = 1  AND ut.ChargeTypeID = 6 THEN ut.TransactionAmount END) AS SpecialDebit
  , SUM(CASE WHEN ut.TransactionTypeID = 2  AND ut.ChargeTypeID = 1 THEN ut.TransactionAmount END) AS NormalCredit
  , SUM(CASE WHEN ut.TransactionTypeID = 2  AND ut.ChargeTypeID = 6 THEN ut.TransactionAmount END) AS SpecialCredit
  , SUM(CASE WHEN ut.TransactionTypeID = 1  THEN ut.TransactionAmount WHEN ut.TransactionTypeID = 2  THEN ut.TransactionAmount * -1 END) AS TotalAmount
FROM users u
LEFT OUTER JOIN UsersTransactions ut ON u.userid = ut.UserID 
INNER JOIN TransactionTypes tt ON ut.TransactionTypeID = tt.TransactionTypeID  
INNER JOIN ChargeTypes ct ON ut.ChargeTypeID = ct.ChargeTypeID
WHERE u.test = 5
GROUP BY u.userID
ORDER BY u.userID

Results

| userid |      name | SpecialBalance | TotalBalance |
|--------|-----------|----------------|--------------|
|      1 |      Bill |             -3 |           -3 |
|      3 |     Rufus |             10 |           20 |
|      4 | SilentBob |              0 |            0 |
|      5 |       Jay |              0 |          500 |

这将输出用于测试= 5过滤的用户ID 1,3,4和5的必要字段.由于似乎没有来自表TransactionTypes和ChargeTypes的任何数据,因此可以删除那些INNER JOIN以显着加快查询速度.

因此,当您到达CF时,您可以简化查询.尝试:

<cfquery name="getUsersTransactions" datasource="db">
    SELECT s1.userid
      , s1.name
      , ( s1.SpecialDebit - s1.SpecialCredit ) AS SpecialBalance
      , ( (s1.NormalDebit + s1.SpecialDebit) - (s1.NormalCredit + s1.SpecialCredit) ) AS TotalBalance
    FROM (
      SELECT u.userid
        , u.name
        , SUM(CASE WHEN ut.TransactionTypeID = 1  AND ut.ChargeTypeID = 1 THEN ut.TransactionAmount ELSE 0 END) AS NormalDebit
        , SUM(CASE WHEN ut.TransactionTypeID = 1  AND ut.ChargeTypeID = 6 THEN ut.TransactionAmount ELSE 0 END) AS SpecialDebit
        , SUM(CASE WHEN ut.TransactionTypeID = 2  AND ut.ChargeTypeID = 1 THEN ut.TransactionAmount ELSE 0 END) AS NormalCredit
        , SUM(CASE WHEN ut.TransactionTypeID = 2  AND ut.ChargeTypeID = 6 THEN ut.TransactionAmount ELSE 0 END) AS SpecialCredit
      FROM users u
      LEFT OUTER JOIN UsersTransactions ut ON u.userid = ut.UserID 
      WHERE u.test = 5
      GROUP BY u.userID
    ) s1
</cfquery>

<table>
<th>UserID</th>
<th>User Name</th>
<th>UserSpecialBalance</th>
<th>UserBalance</th>
<cfoutput query="getUsersTransactions">
    <!--- Build out the table rows in here--->
    <tr>
        <td>#getUsersTransactions.userID#</td>
        <td>#getUsersTransactions.name#</td>
        <td>#getUsersTransactions.SpecialBalance#</td>
        <td>#getUsersTransactions.TotalBalance#</td>
    </tr>
</cfoutput>
</table>

注意:将ELSE 0添加到CASE语句将过滤掉将破坏求和的查询中的NULL值. CF仍会将这些结果显示为空白,但数据可能有误.

标签:sql,mysql,coldfusion
来源: https://codeday.me/bug/20190724/1522047.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有