我正在Rails中对我的PG数据库进行原始sql查询。当我在WHERE子句中只使用一个日期条件时效果很好,但是当我使用2个日期条件时,它不能按预期工作。要查看结果,我会通过结果对象为每个结果执行一次并将其打印到控制台。
只有一个条件:
connection = ActiveRecord::Base.connection()
results = connection.execute("SELECT *
FROM training_employees
LEFT JOIN trainings
ON training_employees.training_id = trainings.id
WHERE trainings.date >='2014-06-29'")
results.each do |row|
puts row
end
返回
{"id"=>"1", "employee_id"=>"2", "training_id"=>"1",
"created_at"=>"2014-06-29 06:44:13.261074",
"updated_at"=>"2014-06-29 06:44:13.261074",
"name"=>"Incendios", "date"=>"2014-06-30 02:43:00",
"expected_attendance"=>"20", "service_company_id"=>"1"}
{"id"=>"1", "employee_id"=>"3", "training_id"=>"1",
"created_at"=>"2014-06-29 06:44:13.261074",
"updated_at"=>"2014-06-29 06:44:13.261074",
"name"=>"Incendios",
"date"=>"2014-06-30 02:43:00",
"expected_attendance"=>"20", "service_company_id"=>"1"}
{"id"=>"1", "employee_id"=>"7", "training_id"=>"1",
"created_at"=>"2014-06-29 06:44:13.261074",
"updated_at"=>"2014-06-29 06:44:13.261074",
"name"=>"Incendios", "date"=>"2014-06-30 02:43:00",
"expected_attendance"=>"20", "service_company_id"=>"1"}
{"id"=>"1", "employee_id"=>"9", "training_id"=>"1",
"created_at"=>"2014-06-29 06:44:13.261074",
"updated_at"=>"2014-06-29 06:44:13.261074",
"name"=>"Incendios", "date"=>"2014-06-30 02:43:00",
"expected_attendance"=>"20", "service_company_id"=>"1"}
{"id"=>"1", "employee_id"=>"10", "training_id"=>"1",
"created_at"=>"2014-06-29 06:44:13.261074",
"updated_at"=>"2014-06-29 06:44:13.261074",
"name"=>"Incendios", "date"=>"2014-06-30 02:43:00",
"expected_attendance"=>"20", "service_company_id"=>"1"}
=> #<PG::Result:0x007fa8b9cfc038
@connection=#<PG::Connection:0x007fa8b994fcf0
@socket_io=nil, @notice_receiver=nil,
@notice_processor=nil>>
当我使用两个条件进行查询时
results = connection.execute("SELECT *
FROM training_employees
LEFT JOIN trainings
ON training_employees.training_id = trainings.id
WHERE trainings.date >='2014-06-29'
AND trainings.date <='2014-06-30'")
results.each do |row|
puts row
end
仅返回此内容,而不是使用一个条件
返回记录列表 => #<PG::Result:0x007fa8b75c5398
@connection=#<PG::Connection:0x007fa8b994fcf0 @socket_io=nil,
@notice_receiver=nil, @notice_processor=nil>>
我已经单独测试了条件并返回了我的期望(日期范围之间存在记录)
这些是我的模特
Training(id: integer, name: string, date: datetime,
expected_attendance: integer, created_at: datetime,
updated_at: datetime, service_company_id: integer)
TrainingEmployee(id: integer, employee_id: integer,
training_id: integer, created_at:
datetime, updated_at: datetime)
我正在使用ruby 2.1.1和Rails 4.1.0。
答案 0 :(得分:2)
你的问题是你实际上只是在30日的午夜。当您的类型转换为比较时,您的查询实际上是这样的:
SELECT *
FROM training_employees
LEFT JOIN trainings
ON training_employees.training_id = trainings.id
WHERE trainings.date >='2014-06-29 00:00:00.000000'
AND trainings.date <='2014-06-30 00:00:00.000000'
....所以当然不会包含trainings
与date = "2014-06-30 02:43:00"
的记录。查询日期/时间/时间戳的正确方法是使用exclusive upper bound - 即trainings.date < '2014-07-01'
。
这也导致没有任何记录被退回,因为你实际上没有LEFT JOIN
,你实际上有INNER JOIN
。这就是为什么;当WHERE
子句滚动时, LEFT JOIN
并且没有记录的任何内容都会使这些条件null
并导致数据库排除它们。如果您确实需要LEFT JOIN
,则需要将条件移至ON
子句。如果你确实想要一个INNER JOIN
,你应该仍然将它们移到ON
子句,因为这会使连接更加明显。
除此之外:trainings.date
实际代表什么?这个名字非常含糊......
答案 1 :(得分:0)
date
中的所有时间戳实际上都大于2014-06-30,因为其中五个都是:
"date"=>"2014-06-30 02:43:00"
2014-06-30
的日期对应于2014-06-30 00:00:00
的时间戳,因此您的时间戳的时间组件会干扰您的查询逻辑。
解决方案是使用date
列来存储日期,而不是时间戳。然后你就没有时区,时间,......问题。