【发布时间】:2013-12-10 12:06:31
【问题描述】:
我有以下架构:
User:
---
ID
---
Tasks:
-------------------
ID | classification
-------------------
Timesheets:
------------------------
ID | task_id | user_id
------------------------
TimesheetItem:
--------------------------------
ID | timesheet_id | hours | date
--------------------------------
协会:
class User
has_many :timesheets
end
class Task
has_many :timesheets
end
class Timesheet
has_many :timesheet_items
belongs_to :user
belongs_to :task
end
class TimesheetItem
belongs_to :timesheet
end
分类可以是“计费”或“不可计费”。 现在我需要为每个用户找到可计费和不可计费小时的总和,如下所示:
-----------------------------------
|user_id | billable | nonbillable |
-----------------------------------
我在 Rails 中所做的是:
User.joins(:timesheets, :timesheets => :task, :timesheets => :timesheet_items)
.select("SUM(CASE
WHEN tasks.task_classification = 'Billable'
THEN timesheet_items.hours
ELSE
0
END) as billable,
SUM(CASE
WHEN tasks.task_classification = 'Non-Billable'
THEN timesheet_items.hours
ELSE 0
END) as nonbillable")
但 MySQL 给出错误“tasks.classification”是未知列。看看正在生成的查询,这是可以理解的:
SELECT SUM(CASE WHEN tasks.classification = 'Billable' THEN hours ELSE 0 END) as billable, SUM(CASE WHEN tasks.classification = 'Non-Billable' THEN hours ELSE 0 END) as nonbillable FROM `users` INNER JOIN `timesheets` ON `timesheets`.`user_id` = `users`.`id` INNER JOIN `timesheet_items` ON `timesheet_items`.`timesheet_id` = `timesheets`.`id`
如您所见,未加入任务表。
我如何实现这一目标?谢谢。
编辑:
我有点继续使用一个简单的 sql 查询,它加入了任务表以获得结果,因为这些数据只在一个地方使用并且很少使用。
但现在我需要按月对小时数进行分组,并找出每个用户记录计费和非计费小时的小时数。例如。
结果:
-----------------------------------------------
user_id | month | BillableHrs | NonBillableHRS|
-----------------------------------------------
我试过group(user_id, MONTH(date)) 但是.. 结果很奇怪。我怎样才能获得这种信息?
顺便说一句,将连接更改为:
joins(:timesheets, :timesheets => [:task, :timesheet_items])
解决了未找到列的问题:)
我终于找到了这个解决方案。任何优化的想法?
SELECT
users.id as user_id,
users.name as user_name,
CONCAT(MONTHNAME(date)," ",YEAR(date)) as month,
SUM( CASE
WHEN tasks.task_classification = "Billable"
THEN hours
ELSE
0
END ) as blb_sum,
SUM( CASE
WHEN tasks.task_classification = "Non-Billable"
THEN hours
ELSE
0
END ) as nblb_sum
FROM `users`
INNER JOIN `timesheets` ON `timesheets`.`user_id` = `users`.`id`
INNER JOIN `timesheet_items` ON `timesheet_items`.`timesheet_id` = `timesheets`.`id`
INNER JOIN `tasks` ON `timesheets`.`task_id` = `tasks`.`id`
WHERE
timesheet_items.date >= '2013-11-1' AND
timesheet_items.date <= '2013-11-31'
【问题讨论】:
-
这是一个丑陋的 activerecord 和 SQL 组合——我只是将它作为 SQL 语句运行。
-
哈哈。是啊,你说得对。我正在考虑这样做。但是AR中有什么方法可以做案例吗?顺便说一句,我将为此使用普通 SQL。
-
嗯,我不知道。不过,我会提出另一个建议作为答案,只是看看人们对此有何看法。
-
感谢你们的解决方案!!你能帮我找到如何按月对总和进行分组吗?谢谢!
标签: mysql ruby-on-rails join