2017-10-16 46 views
0

當我運行此查詢...PG ::語法錯誤:錯誤在那裏的Rails與TO_DATE條款

OnlineCourseRegistration.where("exam_completed_at.strftime('%m/%d/%Y').to_date + 360 = ?", Date.today) 

我得到這個錯誤...

2.3.0 :012 > OnlineCourseRegistration.where("exam_completed_at.strftime('%m/%d/%Y').to_date = ?", Date.today) 
    OnlineCourseRegistration Load (0.5ms) SELECT "class_registrations".* FROM "class_registrations" INNER JOIN "course_classes" ON "course_classes"."id" = "class_registrations"."course_class_id" INNER JOIN "courses" ON "courses"."id" = "course_classes"."course_id" INNER JOIN "users" ON "users"."id" = "class_registrations"."user_id" WHERE (course_classes.class_type = 'online') AND (exam_completed_at.strftime('%m/%d/%Y').to_date = '2017-10-16') 
PG::SyntaxError: ERROR: syntax error at or near "." 
LINE 1: ...line') AND (exam_completed_at.strftime('%m/%d/%Y').to_date =... 
                  ^
: SELECT "class_registrations".* FROM "class_registrations" INNER JOIN "course_classes" ON "course_classes"."id" = "class_registrations"."course_class_id" INNER JOIN "courses" ON "courses"."id" = "course_classes"."course_id" INNER JOIN "users" ON "users"."id" = "class_registrations"."user_id" WHERE (course_classes.class_type = 'online') AND (exam_completed_at.strftime('%m/%d/%Y').to_date = '2017-10-16') 
ActiveRecord::StatementInvalid: PG::SyntaxError: ERROR: syntax error at or near "." 
LINE 1: ...line') AND (exam_completed_at.strftime('%m/%d/%Y').to_date =... 
                  ^
: SELECT "class_registrations".* FROM "class_registrations" INNER JOIN "course_classes" ON "course_classes"."id" = "class_registrations"."course_class_id" INNER JOIN "courses" ON "courses"."id" = "course_classes"."course_id" INNER JOIN "users" ON "users"."id" = "class_registrations"."user_id" WHERE (course_classes.class_type = 'online') AND (exam_completed_at.strftime('%m/%d/%Y').to_date = '2017-10-16') 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/postgresql_adapter.rb:774:in `async_exec' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/postgresql_adapter.rb:774:in `exec_no_cache' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:138:in `block in exec_query' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract_adapter.rb:435:in `block in log' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activesupport-4.0.2/lib/active_support/notifications/instrumenter.rb:20:in `instrument' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract_adapter.rb:430:in `log' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/postgresql/database_statements.rb:137:in `exec_query' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/postgresql_adapter.rb:891:in `select' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/database_statements.rb:24:in `select_all' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/querying.rb:36:in `find_by_sql' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/relation.rb:585:in `exec_queries' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/relation.rb:471:in `load' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/relation.rb:220:in `to_a' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/relation.rb:598:in `exec_queries' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/relation.rb:471:in `load' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/relation.rb:220:in `to_a' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/activerecord-4.0.2/lib/active_record/relation.rb:573:in `inspect' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/railties-4.0.2/lib/rails/commands/console.rb:90:in `start' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/railties-4.0.2/lib/rails/commands/console.rb:9:in `start' 
    from /Users/marklocklear/.rvm/gems/ruby-2.3.0/gems/railties-4.0.2/lib/rails/commands.rb:62:in `<top (required)>' 
    from bin/rails:4:in `require' 

我試圖改變了報價和反引號,但沒有運氣。

+2

我不知道紅寶石。但是strftime是一個ruby函數,你試圖將它用作postgresql函數。 –

+0

如果你正在尋找Rails方式:'OnlineCourseRegistration.where({exam_completed_at:(Time.now.midnight - 361.day)..(Time.now.midnight - 360.day)})' – ninjarails

回答

0

牙多少捕鯨和咬牙切齒之後,我覺得有我要找的查詢。我仍在測試,但到目前爲止它似乎工作。

只是爲我試圖運行的原始查詢添加一些上下文。用簡單的英語,我試圖找到其exam_completed_at日期比今天的日期早一年的記錄。換言之,我正在查找記錄,其中exam_completed_at日期是今天的日期減去360(或一年)。

這裏是我想出了:

OnlineCourseRegistration.where("exam_completed_at BETWEEN ? AND ?", DateTime.now.beginning_of_day - 1.year, DateTime.now.end_of_day - 1.year) 

作爲一個全面的檢查,看看這個記錄:

2.3.0 :276 > OnlineCourseRegistration.find 14340 
D, [2017-10-17T10:01:54.622455 #35257] DEBUG -- : OnlineCourseRegistration Load (0.9ms) SELECT "class_registrations".* FROM "class_registrations" INNER JOIN "course_classes" ON "course_classes"."id" = "class_registrations"."course_class_id" INNER JOIN "courses" ON "courses"."id" = "course_classes"."course_id" INNER JOIN "users" ON "users"."id" = "class_registrations"."user_id" WHERE (course_classes.class_type = 'online') AND "class_registrations"."id" = $1 LIMIT 1 [["id", 14340]] 
=> #<OnlineCourseRegistration id: 14340, cart_id: 15093, user_id: 7090, course_class_id: 681, created_at: "2017-09-05 15:19:23", updated_at: "2017-10-17 13:29:08", exam_attempts: 0, exam_completed_at: "2016-10-17 13:29:03", evaluation_completed_at: nil, status: "Active", score: nil, add_extension: false, retest_cart_id: nil, retest_purchased_at: nil> 

...並注意exam_completed_at日期爲2016-10-17 13:29:03。現在當我運行查詢時,我得到相同的記錄返回:

2.3.0 :275 > OnlineCourseRegistration.where("exam_completed_at BETWEEN ? AND ?", DateTime.now.beginning_of_day - 1.year, DateTime.now.end_of_day - 1.year) 
D, [2017-10-17T09:59:27.832326 #35257] DEBUG -- : OnlineCourseRegistration Load (2.2ms) SELECT "class_registrations".* FROM "class_registrations" INNER JOIN "course_classes" ON "course_classes"."id" = "class_registrations"."course_class_id" INNER JOIN "courses" ON "courses"."id" = "course_classes"."course_id" INNER JOIN "users" ON "users"."id" = "class_registrations"."user_id" WHERE (course_classes.class_type = 'online') AND (exam_completed_at BETWEEN '2016-10-17 04:00:00.000000' AND '2016-10-18 03:59:59.000000') 
=> #<ActiveRecord::Relation [#<OnlineCourseRegistration id: 14340, cart_id: 15093, user_id: 7090, course_class_id: 681, created_at: "2017-09-05 15:19:23", updated_at: "2017-10-17 13:29:08", exam_attempts: 0, exam_completed_at: "2016-10-17 13:29:03", evaluation_completed_at: nil, status: "Active", score: nil, add_extension: false, retest_cart_id: nil, retest_purchased_at: nil>, #<OnlineCourseRegistration id: 14267, cart_id: 15004, user_id: 7069, course_class_id: 681, created_at: "2017-07-15 22:06:06", updated_at: "2017-10-17 13:49:17", exam_attempts: 1, exam_completed_at: "2016-10-17 13:49:11", evaluation_completed_at: "2017-07-20 23:59:01", status: "Completed", score: "87", add_extension: false, retest_cart_id: nil, retest_purchased_at: nil>]> 
0

你有你的SQL和ruby混合。

exam_completed_at.strftime('%m/%d/%Y').to_date是Ruby代碼,但您已將它運行在SQL中。修復並使用漂亮AREL

一種方法(假設exam_completed_at是數據庫字段來過濾上,而不是局部變量)與日期範圍:

where(
    exam_completed_at: 
    (Date.today.beginning_of_day - 360.days)..(Date.today.end_of_day - 360.days) 
) 
0

試試這個:

OnlineCourseRegistration.where("(created_at - current_timestamp) < interval '360 day'") 
+0

問題是,不會在'exam_completed_at'上使用索引。更好地使用'where(exam_completed_at = CURRENT_DATE - INTERVAL'12 months')' –

+1

同意索引但你的語法不正確。 – ninjarails

1

postgresql你有to_char函數將日期轉換爲字符串。

to_char(timestamp, text) 

但你需要一個時間戳類型,所以你需要使用current_timestamp

因此,要360天前獲得時間戳使用:

current_timestamp - interval '360 days' 

要獲得該日期的字符串:

SQL DEMO

to_char(current_timestamp - interval '360 days', 'MM/dd/YYYY') 

這會生成一個常數值,因此可以與索引一起使用。

所以Ruby代碼應該是:

.where("exam_completed_at = to_char(current_timestamp - interval '360 days', 'MM/dd/YYYY') 
+0

我不認爲這會奏效。它比較整個時間戳,而我們只需要比較幾天的時間間隔。 – ninjarails

+0

@MingJin你看過演示了嗎?這將時間戳轉換爲字符串。並且因爲OP使用'strftime',我們需要將當前時間轉換爲字符串,這就是'to_char'的作用 –

+0

瞭解。但仍然會引起操作員錯誤,因爲它將時間戳與日期進行比較。 – ninjarails