【问题标题】:Complex MySQL query : solution to work with views (datatables...)复杂的 MySQL 查询:使用视图(数据表...)的解决方案
【发布时间】:2016-09-22 21:24:58
【问题描述】:

我需要在 php 脚本中使用带有连接、子查询等的复杂查询来为数据表服务器端进程生成 Json。 Datatables 不接受子查询,所以我需要一个“平面”查询。我想生成一个视图,但在 MySQL 视图上也不接受子查询! 这是 MySQL 查询。你会推荐什么?

SELECT a.Customers
    ,a.Agent
    ,a.status_name AS Current_Status
    ,round(c.LTGGR - e.LT_TotBonus, 0) AS LT_NGR
    ,CONCAT (
        round(e.LT_TotBonus / c.LTRM * 100, 0)
        ,'%'
        ) AS LT_Bonus_RM_per
    ,CONCAT (
        'x'
        ,round(c.LTBETS / (c.LTRM + e.LT_TotBonus), 0)
        ) AS LT_Wagering
    ,coalesce(d.Last_30D_RM, 0) AS Last_30D_RM
    ,coalesce(d.Last_30D_NGR, 0) AS Last_30D_NGR
    ,coalesce(g.CashBack_Last30D, 0) AS Cash_Back_30D
    ,CONCAT (
        (f.cash_back_BO_per * 100)
        ,'%'
        ) AS status_cash_Back_BO_per
    ,CONCAT (
        f.cash_back_per * 100
        ,'%'
        ) AS cash_back_percent
    ,CASE 
        WHEN f.cash_back_per = 0
            THEN 0
        WHEN c.LTGGR - e.LT_TotBonus < 0
            THEN 0
        WHEN d.Last_30D_RM < 0
            THEN 0
        WHEN e.LT_TotBonus / c.LTRM * 100 >= f.cash_back_BO_per * 100
            THEN 0
        WHEN round(d.Last_30D_NGR * f.cash_back_per, 0) - coalesce(g.CashBack_Last30D, 0) < 0
            THEN 0
        WHEN isnull(d.Last_30D_NGR)
            THEN 0
        WHEN d.Last_30D_NGR < 0
            THEN 0
        ELSE round(d.Last_30D_NGR * f.cash_back_per, 0)
        END AS cash_back_calc
    ,CASE 
        WHEN f.cash_back_per = 0
            THEN 'No Cash Back for Status'
        WHEN c.LTGGR - e.LT_TotBonus < 0
            THEN 'LT NGR <0'
        WHEN d.Last_30D_RM < 0
            THEN 'No RM Deposit in 30D'
        WHEN e.LT_TotBonus / c.LTRM * 100 >= f.cash_back_BO_per * 100
            THEN 'Above LT Bonus Percentage'
        WHEN coalesce(g.CashBack_Last30D, 0) > 0
            AND round(d.Last_30D_NGR * f.cash_back_per, 0) - coalesce(g.CashBack_Last30D, 0) < 0
            THEN 'CashBack in 30D> Cash Back Calculated'
        WHEN isnull(d.Last_30D_NGR)
            THEN 'No NGR in 30D'
        WHEN d.Last_30D_NGR < 0
            THEN 'Negative NGR in 30D'
        ELSE ''
        END AS note
FROM (
    (
        SELECT *
        FROM players_levels
        WHERE date_format(Date_Status, '%Y-%m') = (
                SELECT date_format(max(players_levels.Date_Status), '%Y-%m')
                FROM players_levels
                )
        GROUP BY Customers
        ) a LEFT JOIN (
        SELECT *
        FROM players_levels
        WHERE date_format(Date_Status, '%Y-%m') = (
                SELECT date_format(max(players_levels.Date_Status) - INTERVAL 1 MONTH, '%Y-%m')
                FROM players_levels
                )
        ) b ON a.Customers = b.Customers
    LEFT JOIN (
        SELECT Customers
            ,sum(Total_Win_Loss) AS LTGGR
            ,sum(Real_Money) AS LTRM
            ,sum(Total_Bets) AS LTBETS
        FROM Online_customer_activity_v2
        GROUP BY Customers
        ) c ON a.Customers = c.Customers
    LEFT JOIN (
        SELECT Customers
            ,sum(Real_Money) AS Last_30D_RM
            ,sum(Total_Win_Loss) - sum(_Bonuses) AS Last_30D_NGR
        FROM Online_customer_activity_v2
        WHERE Online_customer_activity_v2.DATE >= (NOW() - INTERVAL 1 MONTH)
        GROUP BY Customers
        ) d ON a.Customers = d.Customers
    LEFT JOIN (
        SELECT Account
            ,sum(CASE 
                    WHEN Method LIKE '%BONUS%'
                        AND (Method NOT LIKE '%CASHBACKBONUS%')
                        THEN Amount
                    ELSE 0
                    END) LT_Bo_No_CashB
            ,sum(CASE 
                    WHEN Method LIKE 'CASHBACKBONUS'
                        THEN Amount
                    ELSE 0
                    END) LT_CashBack
            ,sum(CASE 
                    WHEN Method LIKE '%BONUS%'
                        AND (Method NOT LIKE '%CASHBACKBONUS%')
                        THEN Amount
                    ELSE 0
                    END) + sum(CASE 
                    WHEN Method LIKE 'CASHBACKBONUS'
                        THEN Amount
                    ELSE 0
                    END) AS LT_TotBonus
        FROM `Online_dailyfinance_v2`
        GROUP BY Account
        ) e ON a.Customers = e.Account
    LEFT JOIN (
        SELECT loyalty_points.status_name
            ,loyalty_points.cash_back_per
            ,loyalty_points.cash_back_BO_per
        FROM loyalty_points
        ) f ON a.status_name = f.status_name
    LEFT JOIN (
        SELECT Account
            ,sum(CASE 
                    WHEN Method LIKE 'CASHBACKBONUS'
                        THEN Amount
                    ELSE 0
                    END) AS CashBack_Last30D
        FROM `Online_dailyfinance_v2`
        WHERE Online_dailyfinance_v2.DATE >= (NOW() - INTERVAL 1 MONTH)
        GROUP BY Account
        ) g ON a.Customers = g.Account
    )
ORDER BY c.LTRM DESC

【问题讨论】:

  • 这不是代码翻译服务...如果您不能使用子查询,那么您将不得不重写以不使用它们。
  • 好的。感谢您的有用评论。也许有人可以给我一个提示......
  • 服务器端 PHP 处理程序有一个解决方法来启用对 JOIN 的支持,请参阅 this answer

标签: php mysql datatables subquery


【解决方案1】:

@Renaud,我赞赏你坚持创建这个雄心勃勃的查询。突出的一件事是您必须执行“LIKE”语句。我使用了很多以“TINYINT”作为“文本”键的“参考表”。所以我可能有“5”作为“现金奖励”的关键,而“3”作为简单的“奖励”的关键。你看那可以简单的事情吗?我希望态度不好的脚本小子不要拒绝我的提示/答案,但是每当我遇到需要这样查询的情况时,我通常最终会创建包含我需要的数据范围的汇总表。它不经常,但偶尔需要。如果它使编码更容易,我什至会违反第 3 范式(哦,太可怕了!)。但我是控制我的数据库的人,所以我不知道你是否可以进行这些修改。我从事 DB 的工作已有 25 年多的时间了,所以请按照您认为值得的方式去做。

【讨论】:

  • .. 是的,我也不喜欢无用和嘲讽的“答案”。我特别不喜欢 RTFM,因为我总是使用 RTFM,而且手册常常含糊不清。例如:查看 PDO BindValue 上的 def 和 BindParam 上的 def。那会引起一大堆问题,但仍然有人会说“RTFM”。我会保留我对这些人的看法。
猜你喜欢
  • 1970-01-01
  • 2022-12-19
  • 1970-01-01
  • 2013-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-02
  • 1970-01-01
相关资源
最近更新 更多