I have a Rails 3.2.14 app where I'm trying to use the chartkick and groupdate gem to generate some charts. I've installed both gems, and I'm trying to do some test queries from the console on my Call model.
Call.group_by_day(:created_at)
I raise an exception and get the following error:
Call Load (8.8ms) SELECT "calls".* FROM "calls" WHERE (created_at IS NOT NULL) GROUP BY (DATE_TRUNC('week', (created_at::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'America/Chicago') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'America/Chicago'
ActiveRecord::StatementInvalid: PG::Error: ERROR: column "calls.id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT "calls".* FROM "calls" WHERE (created_at IS NOT NULL...
^
: SELECT "calls".* FROM "calls" WHERE (created_at IS NOT NULL) GROUP BY (DATE_TRUNC('week', (created_at::timestamptz - INTERVAL '6 day' - INTERVAL '0' hour) AT TIME ZONE 'America/Chicago') + INTERVAL '6 day' + INTERVAL '0' hour) AT TIME ZONE 'America/Chicago
Is there something I'm supposed to do to make this work? Is there some sort of scope I need to create to make this work? I'm new to the gems so any help would be appreciated.
Apparently I wasn't calling this correctly.
I needed to call Call.group_by_day(:created_at).count to make this work.
Related
I have a SQL query which gives different set of result when I use condition
DATE_TRUNC('DAY', timestamp) BETWEEN date_trunc('DAY', NOW()) - interval '14' day AND date_trunc('DAY', NOW())
and a different result when I use condition
timestamp BETWEEN date_trunc('DAY', NOW()) - interval '14' day AND date_trunc('DAY', NOW())
After cross checking both the query results I found that first condition is giving correct result.
Can someone please tell me the difference between both the conditions.
Thanks in advance
timestamp has a time component.
date_trunc(day, timestamp) removes the time component.
The second part of the comparison is different. The first version returns any time on the current day.
The second version only returns midnight on the current day.
Incidentally, I would recommend:
where timestamp >= current_date - interval '14 day' and
timestamp < current_date + interval '1 day'
This works, regardless of whether the timestamp column has a time component or not. And, it is friendly to the optimizer and index usage.
can anybody convert this oracle expression trunc(add_months(sysdate,3),'Q')-1) to postgresql?
Basically this expression gives you the last day of the current quarter (provided that you remove the last closing parenthese, which otherwise is a syntax error).
In postgres, you could phrase this as:
date_trunc('quarter', current_date) + interval '3 months' - interval '1 day'
This generates a timestamp value, that you can cast if you want a date (this distinction does not exist in Oracle, where a date stores the time component as well).
The Postgres equivalent of your Oracle calculation can be seen below.
select date_trunc('quarter', current_date + interval '3 month') - interval '1 day'
I am working on queries in Amazon RedShift.
I have created in query in which I am getting syntax error but I am unable to know the issue behind it. The query looks OK to me.
Below is the query:
select (TIMESTAMP WITHOUT TIME ZONE 'epoch' + (_action_date::float / 1000000) * INTERVAL '1 second') as eta
where eta >= (SELECT NOW() - INTERVAL '1 DAY')
from trips;
Here, _action_date is a bigint integer so I am converting it into timestamp format also.
I am trying to extract those rows in which _action_date is greater than or equal to yesterday date.
The error I am getting:
Error running query: syntax error at or near "from" LINE 1: ...ta where eta >= (SELECT NOW() - INTERVAL '1 DAY') from trips... ^
Please help me in correcting it. Any help would be highly appreciated.
select (TIMESTAMP WITHOUT TIME ZONE 'epoch' + (_action_date::float / 1000000) *
INTERVAL '1 second') as eta
from trips
where eta >= (SELECT getdate() - INTERVAL '1 DAY');
select *
From #####
where username in ('akhil') and between (now() ::timestamp and now() - interval '1 day'::timestamp)
Getting error in this line .
Error - cannot cast type interval to timestamp without time zone .
You don't need the second cast. You need a column name. Something like this:
select *
from #####
where username in ('akhil') and
<some date column> >= now() - interval '1 day' and
<some date column> < now();
the error is in the second cast
now() - interval '1 day'::timestamp
is interprested as.
now() - (interval '1 day')::timestamp
when you actually mean
(now() - interval '1 day')::timestamp
or possibly you mean
now()::timestamp - interval '1 day'
both are valid, but the the result you'll get when daylight saving starts or stops is different (hint interval '1 day' is the same as interval '24 hours' in the first)
There's a strong possiblity that you should actually be using timestamp with time zone for the database column.
I'm using Arels for creating query. In this query, I use generate_series function. Here is my code:
def generate_series
Arel::Nodes::NamedFunction.new('GENERATE_SERIES', [start_date, end_day, '1 day'])
end
def start_date
Arel::Nodes::SqlLiteral.new(<<-SQL
CASE WHEN DATE_PART('hour', NOW() AT TIME ZONE 'ICT') < #{Time.now - 3days} THEN (CURRENT_DATE - INTERVAL '14 days') ELSE (CURRENT_DATE - INTERVAL '13 days') END
SQL
)
end
def end_date
Arel::Nodes::SqlLiteral.new(<<-SQL
CASE WHEN DATE_PART('hour', NOW() AT TIME ZONE 'ICT') < #{Time.now} THEN (CURRENT_DATE - INTERVAL '1 day') ELSE CURRENT_DATE END
SQL
)
end
When I try to test by generate_series.to_sql. I meet exception:
Arel::Visitors::UnsupportedVisitError: Unsupported argument type:
String. Construct an Arel node instead.
I try to shorter my code for testing:
def generate_series
Arel::Nodes::NamedFunction.new('GENERATE_SERIES', ['19/11/2012', '20/11/2012', '1 day'])
end
The problem is same. Please tell me how can I fix this problem.
You can use Arel::Nodes.build_quoted to quote literals:
def generate_series
Arel::Nodes::NamedFunction.new('GENERATE_SERIES',
[start_date, end_date, Arel::Nodes.build_quoted('1 day')]
)
end
The advantage of this is that you don't have to remember to include and manually escape quotes like you do with Arel::Nodes::SqlLiteral.
Your last parameter should be an Arel::Nodes. So you should wrap 1 day into an Arel::Nodes:SqlLiteral. Here is updated code:
def generate_series
Arel::Nodes::NamedFunction.new('GENERATE_SERIES',
[start_date, end_date, Arel::Nodes::SqlLiteral.new('\'1 day\'')]
)
end
Noted that you must also wrap 1 day inside (single) quotes, i.e: '1 day'. Because if you don't do this, the generated query will be:
GENERATE_SERIES(start, stop, 1 day)
But true query should be:
GENERATE_SERIES(start, stop, '1 day')