SQL Query作为临时RoR(ActiveRecord)模型

时间:2014-04-01 03:09:06

标签: mysql sql ruby-on-rails activerecord view

可悲的是,我找不到有关我正在尝试做什么的更多信息。我会尝试尽可能简短地分解它。

我正在使用遗留数据库,相信我,它也让我感到沮丧,但它就是这样,所以我们必须在这个参数范围内工作。

我有一个包含数十万行的数据库,还有一个特别需要生成的ornery统计/报告。最初它只是在一个大的查询中,但这使得它真的很令人沮丧,因为它不允许非常干的架构。我将查询分解为几个视图并将它们连接在一起(最终在最终视图中),这对于测试/开发来说很好,但是我确信一些读过这个的更高级/经验的人可能已经猜到了,很慢。加速它的最明显的方法是将“where”子句应用于连接在一起的内部视图。这大大加快了整个事情的发展。

所以,考虑到这一点,我想到了自己

  

为什么我不能只创建一个模型并定义它应该使用的大讨厌的union / select infested SQL,并将模型的where子句应用于每个子选择。

我的想法是,这基本上会创建一个“虚拟”模型(我无法通过这个名字找到任何东西,所以我在这里抓住),这些模型在任何地方都不存在,但是当“查询”时它会返回瞬态具有关系的对象(最有可能是其他更持久的模型)。

为了说明,我将发布big-nasty-sql。从角度来看,它基本上是总结/统计联盟销售等的统计数据。

SELECT
    `traffic`.`date` AS `date`,
    `traffic`.`site_id` AS `site_id`,
    `traffic`.`partner_id` AS `partner_id`,
    `traffic`.`visits` AS `visits`,
    `traffic`.`clicks` AS `clicks`,
    `traffic`.`signups` AS `signups`,
    `payout`.`signup_total` AS `signup_total`,
    `payout`.`upgrade_total` AS `upgrade_total`,
    `payout`.`recurring_total` AS `recurring_total`,
    `payout`.`referring_total` AS `referring_total`,
    `payout`.`negative_total` AS `negative_total`,
    `payout`.`fee_total` AS `fee_total`,
    `payout`.`carryover_total` AS `carryover_total`,
    `payout`.`adjustment_total` AS `adjustment_total`,
    `payout`.`payment_total` AS `payment_total`,
    `payout`.`payment_nums` AS `payment_nums`
    FROM (
        ((SELECT CAST(`traffic_date` AS DATE) AS `date`,
            `site_id`,
            `partner_id`,
            Sum(IF(tracking_type = 1, count, 0)) AS `visits`,
            Sum(IF(tracking_type = 6, count, 0)) AS clicks,
            Sum(0)                               AS signups
            FROM `tracking`.`tracking_partner_ad_event`
            WHERE `partner_id` = 1796279
            GROUP BY 1, 2, 3)
        UNION
        (SELECT CAST(`traffic_date` AS DATE) AS `date`,
            `site_id`,
            `partner_id`,
            Sum(count) AS visits,
            Sum(0)     AS clicks,
            Sum(0)     AS signups
            FROM `tracking`.`tracking_partner_traffic_visit`
            WHERE `partner_id` = 1796279
            GROUP BY 1, 2, 3)
        UNION
        (SELECT CAST(`processed_date` AS DATE) as `date`,
            `site_id`,
            `partner_id`,
            Sum(0) AS visits,
            Sum(0) AS clicks,
            Sum(1) AS signups
            FROM `user_account_entry`
            WHERE `trans_type` = 2 AND `status` <> 2 AND `partner_id` = 1796279
            GROUP BY 1, 2, 3)
        ) AS `traffic`
    JOIN
        (SELECT
            `period` AS `period_id`,
            `partner_id`,
            `processed_date`,
            `site_id`,
            SUM(IF(`payout_type`=1, amount, 0)) AS `signup_total`,
            SUM(IF(`payout_type`=2, amount, 0)) AS `upgrade_total`,
            SUM(IF(`payout_type`=3, amount, 0)) AS `recurring_total`,
            SUM(IF(`payout_type`=8, amount, 0)) AS `referring_total`,
            SUM(IF(`payout_type`=4, amount, 0)) AS `negative_total`,
            SUM(IF(`payout_type`=7, amount, 0)) AS `fee_total`,
            SUM(IF(`payout_type`=9, amount, 0)) AS `carryover_total`,
            SUM(IF(`payout_type`=5, amount, 0)) AS `adjustment_total`,
            SUM(IF(`payout_type`=6, amount, 0)) AS `payment_total`,
            GROUP_CONCAT(`payment_num` ORDER BY 1) AS `payment_nums`
        FROM `partner_account_entry` AS `e`
        WHERE `partner_id` = 1796279
        GROUP BY 1,2 ORDER BY 1,2
        ) AS `payout` ON (
        (
            (`traffic`.`date` = `payout`.`processed_date`) AND
            (`traffic`.`site_id` = `payout`.`site_id`) AND
            (`traffic`.`partner_id` = `payout`.`partner_id`)
        )
    )
) GROUP BY 1,2,3 ORDER BY 1

如您所见,通过选择partner_id,此查询得到了显着优化。

TL; DR:我喜欢将SQL包装在模型中,即使任何查询要求提供partner_id,也要模拟可以传递并进一步链接的rails AR Object用。

这是不合理的要求吗?一项艰巨的努力?怎么可以这样做?我找不到令我担心的现有例子,但也让我感到困惑;这不是一个合理的策略,为什么不存在解决方案?

0 个答案:

没有答案