MySQL 重构冗长的查询 [英] MySQL Refactoring Lengthy Query

查看:40
本文介绍了MySQL 重构冗长的查询的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好吧,我非常讨厌自己提出这个问题;但我正在寻找另一种方法来执行此查询,这种方法可能更快也更优雅(这看起来像废话).请告诉我您的想法:

Alright, I totally hate myself for asking this; but I'm looking for another way to do this query, something that might be faster as well as more elegant (this looks like crap). Tell me what you think please:

  SELECT TRUNCATE(SUM(sub.Total),3) AS GrpTotal, sub.ActualDate, 
         TRUNCATE(SUM(sub.BonusAmt),3) AS GrpBonusAmt, sub.UID, 
         sub.CUSTID, YEAR(MIN(sub.ActualDate)) AS Year, pusers.username
  FROM ( SELECT a.UID, a.ActualDate, 'Global Report' AS Report, 
                SUM(a.totalpayment) AS Total, a.CUSTID,
               ((SUM(a.totalpayment)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmt
         FROM `globalreport` a
              LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Amex Residuals' AS Report, 
                SUM(a.payment) AS Total, a.CUSTID,
                ((SUM(a.payment)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmnt
         FROM `amexresiduals` a
              LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL 
         SELECT a.UID, a.ActualDate, 'Compliance Fee' AS Report, 
                SUM(a.profit) AS Total, a.CUSTID, 
                ((SUM(a.profit)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmnt
         FROM `compliancefee` a
              LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Checks On Demand' AS Report, 
                SUM(a.myprofit) AS Total, a.CUSTID, 
                ((SUM(a.myprofit)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmnt
         FROM `geticheck` a
              LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Gift Cards on Demand' AS Report, 
                SUM(a.payment) AS Total, a.CUSTID,
                ((SUM(a.payment)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmnt
         FROM `gcod` a
              LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Global Check' AS Report, 
                SUM(a.myprofit) AS Total, a.CUSTID,
                ((SUM(a.myprofit)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmnt
         FROM `globalcheck` a
              LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Bonus True Up' AS Report, 
                SUM(a.finalpayment) AS Total, a.CUSTID,
                ((SUM(a.finalpayment)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmnt
         FROM `bonustrueup` a
              LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Bonus Take Back - Did Not Activate' AS Report, 
                SUM(a.amount) AS Total, a.CUSTID,
                ((SUM(a.amount)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmnt 
         FROM `bonusadjnosetup` a
              LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Bonus Take Back - Closed Less Than 6 Months' AS Report, 
                SUM(a.amount) AS Total, a.CUSTID,
                ((SUM(a.amount)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmnt
         FROM `bonusadjclosed6mo` a
             LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Month End Fee Rejects' AS Report, 
                SUM(a.amount) AS Total, a.CUSTID, SUM(a.amount) AS BonusAmnt        
         FROM `merchantloss` a
             LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Direct ACH Debits and Credits' AS Report, 
                SUM(a.amount*-1) AS Total, a.CUSTID, SUM(a.amount*-1) AS BonusAmnt
         FROM `dirachdebcred` a
             LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
         UNION ALL
         SELECT a.UID, a.ActualDate, 'Merchant Adjustments' AS Report, 
                SUM(a.amount) AS Total, a.CUSTID,
                ((SUM(a.amount)*IFNULL((u.retention_percent/100),1))+IFNULL(u.bonus_amount,0)) AS BonusAmnt
         FROM `merchantadj` a
             LEFT JOIN `users` u ON u.uid = a.UID
         WHERE true AND a.CUSTID = 1020
         GROUP BY a.ActualDate, a.UID
  ) sub
      LEFT JOIN `pending_users` pusers ON pusers.UID = sub.UID
  WHERE sub.CUSTID = 1020
       AND sub.`UID` NOT IN 
                ( SELECT `UID` 
                  FROM `users` 
                  WHERE `is_admin` AND `company_id` = sub.`CUSTID`)
  GROUP BY sub.ActualDate, sub.UID, sub.Report
  ORDER BY sub.ActualDate ASC

显然,这是一个冗长的查询.我只是不确定它是否必须如此.从本质上讲,我正在收集和总结每个联合表中的不同列,并在最后按该数量分组,以便我可以从所有表中获得总和.

Clearly, this is a lengthy query. I'm just not sure it has to be. Essentially, I'm gathering and summing a different column in each of the unioned tables and grouping by that amount at the very end so I can get a total sum from all tables.

推荐答案

UPDATE

好像我之前的回答不够长......

As if my previous answer wasn't long enough ...

我还会将 JOIN 从内部查询移动到用户表,从内部查询到外部查询,看起来在每种情况下都是相同的.

I'd also move the JOIN to the users table from the inner queries to the outer queries, it looks like it's identical in every case.

但是,我们需要它来计算 BonusAmnt(它似乎总是基于 Total 是什么;除了两个之外,所有这些的计算都是相同的.所以,我也移动了BonusAmnt 计算也适用于外部查询,并使用 CASE 表达式添加检查要执行的计算.

But, we need that for the calculation of BonusAmnt (which appears to always be based on whatever Total is; the calculation is the same for all of them except for two. So, I also moved the BonusAmnt calculation to the outer query as well, and just adding a check for which calculation to do, using a CASE expression.

我可能错过了一些东西.

I may have missed something.

但这是我编写查询的方式.

But here's how I'd write the query.

我将分两部分展示它,将 sub 内联视图的查询与外部查询分开.

I'll show it in two pieces, with the query for the sub inline view separate from the outer query.

  SELECT TRUNCATE(sub.Total,3) AS GrpTotal
       , sub.ActualDate
       , CASE
           WHEN sub.Report IN ('Month End Fee Rejects','Direct ACH Debits and Credits') THEN
             TRUNCATE(sub.Total,3)
           ELSE
             TRUNCATE(sub.Total*IFNULL((u.retention_percent/100),1)+IFNULL(u.bonus_amount,0)),3)
         END AS GrpBonusAmt
       , sub.UID
       , sub.CUSTID
       , YEAR(sub.ActualDate) AS Year
       , pusers.username
    FROM (
           -- query to produce sub goes here
         ) sub
    LEFT
    JOIN `users` u
      ON u.uid = sub.UID
    LEFT
    JOIN `pending_users` pusers
      ON pusers.UID = sub.UID
    LEFT
    JOIN `users` n
      ON n.UID = sub.CUSTID
     AND n.is_admin
   WHERE n.UID IS NULL
   ORDER BY sub.ActualDate, sub.UID, sub.Report

这是第二部分.这是作为内联视图卡在上面部分中间的查询.这是为外部查询生成 sub 行源的查询:

And here is the second part. This is the query that gets stuck into the middle of the part above, as an inline view. This is the query that that produces sub row source for the outer query:

           SELECT 'Global Report' AS Report
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.totalpayment) AS Total
             FROM `globalreport` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Amex Residuals'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.payment) AS Total
             FROM `amexresiduals` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Compliance Fee'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.profit) AS Total
             FROM `compliancefee` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Checks On Demand'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.myprofit) AS Total
             FROM `geticheck` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Gift Cards on Demand'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.payment) AS Total
             FROM `gcod` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Global Check' AS Report
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.myprofit) AS Total
             FROM `globalcheck` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Bonus True Up'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.finalpayment) AS Total
             FROM `bonustrueup` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Bonus Take Back - Did Not Activate'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.amount) AS Total
             FROM `bonusadjnosetup` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Bonus Take Back - Closed Less Than 6 Months'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.amount) AS Total
             FROM `bonusadjclosed6mo` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Month End Fee Rejects'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.amount) AS Total
             FROM `merchantloss` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Direct ACH Debits and Credits'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.amount*-1) AS Total
             FROM `dirachdebcred` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID
            UNION ALL
           SELECT 'Merchant Adjustments'
                , a.UID, a.ActualDate, a.CUSTID
                , SUM(a.amount) AS Total
             FROM `merchantadj` a
            WHERE a.CUSTID = 1020
            GROUP BY a.ActualDate, a.UID

这篇关于MySQL 重构冗长的查询的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆