Why does AVG query not work after a month in Postgres? - sql

I have been using this query in Postgres for a month, and it has been working fine:
SELECT
DATE_TRUNC('hour', created_at::timestamp) AS datetime,
AVG(temperature_1) as temperature_1
FROM
main_data
WHERE
created_at BETWEEN '2022-01-22 01:00:00' AND '2022-01-22 3:00:00'
GROUP BY
DATE_TRUNC('hour', created_at)
now when I use the query I get this error:
ERROR: column "main_data.created_at" must appear in the GROUP BY clause or be used in an aggregate function
LINE 2: DATE_TRUNC('hour', created_at::timestamp) as datetime,
^
SQL state: 42803
Character: 27
I have not done any update.
This the created_at field in my Postgres database

When using group by keywords your column format (with the cast, etc) should same format in group by operation
SELECT
DATE_TRUNC('hour', created_at::timestamp) as datetime,
AVG(temperature_1) as temperature_1
FROM main_data
where created_at BETWEEN '2022-01-22 01:00:00' AND '2022-01-22 3:00:00'
GROUP BY DATE_TRUNC('hour', created_at::timestamp)

This would happen if the type of created_at changed to something which is not timestamp. For example, timestamptz.
Demonstration
The casting should not be necessary.

Related

How to extract year, month or day from BIGINT epoch timestamp when inserting in Redshift

I would like to extract a date format like month, year or day from a BIGINT timestamp 1543258003796 in the Redshift SQL environment when inserting data into a table.
I have a table like this:
CREATE TABLE time_table (
month_date character varying(20),
year_date character varying(20),
);
Now I want to populate the table time_table with data from another table ts_table that has a column with timestamp as BIGINT type:
INSERT INTO time_table (month_date, year_date)
SELECT EXTRACT(month from ts.timestamp) as month_date,
EXTRACT(year from ts.timestamp) as year_date
FROM ts_table ts;
It raises an error because ts.timestamp is a BIGINT. Should I first cast the BIGINT into something else? Or is there another function to perform this action? I tried several things but I am still not able to find a solution.
I assume that these BIGINT dates are epoch dates. So you first need to convert this to a timestamp - for example like so:
select timestamp 'epoch' + t.timestamp * interval '1 second' AS timest
from ts_table t;
Now this isn't want you want but it gets you into a timestamp data type and opens up the useful functions available to you.
Step 2 is to EXTRACT the year and month from this. Putting these together you get:
WITH ts_conv as (
select timestamp 'epoch' + t.timestamp * interval '1 second' AS
timest
from ts_table t
)
SELECT EXTRACT(month from ts.timest) as month_date,
EXTRACT(year from ts.timest) as year_date
FROM ts_conv ts;
And this of course can be inside your INSERT statement.

Extract hour of the day from a timestamp in Big Query SQL ('FROM' error)

I want to extract the hour of the day from the created_at timestamp (line 3) in the second column via Big Query SQL. With my current code I get the error: "Encountered " "FROM" "FROM "" at line 3, column 18. Was expecting: ")" ..."
Current code:
SELECT
date(created_at) as date,
EXTRACT(HOUR FROM created_at) AS hour,
sum(net_revenue) as net_revenue,
count(order_unique_id) as orders
FROM [source]
WHERE DATE(created_at) BETWEEN DATE(DATE_ADD(CURRENT_DATE(), -2, 'DAY')) AND CURRENT_DATE()
GROUP BY 1,2
Thanks in advance for helping!
The only error I see in your query is in the WHERE clause. Presumably you intend:
WHERE DATE(created_at) BETWEEN DATE_ADD(CURRENT_DATE(), INTERVAL -2 DAY') AND CURRENT_DATE()
As I see from your example, created_at column is not DATE data type.
While, EXTRACT(part FROM date_expression) function requires date data type as argument (https://cloud.google.com/bigquery/docs/reference/standard-sql/date_functions#extract)
So, you have to construct date like you do in second line:
SELECT
date(created_at) as date,
EXTRACT(HOUR FROM DATE(created_at)) AS hour,
...

Postgresql Distinct Statement

How can i get the minutes distinct value with timestamp ...
Like , if table contains 1 minute 100 records are there...so i want count of records present or not per minute ...
For example,
SELECT DISTINCT(timestamp) FROM customers WHERE DATE(timestamp) = CURRENT_DATE
Result should be ..like
timestamp record
30-12-2019 11:30 5
30-12-2019 11:31 8
One option would be ::date conversion for timestamp column including GROUP BY :
SELECT timestamp, count(*)
FROM tab
WHERE timestamp::date = current_date
GROUP BY timestamp
Demo for current day
timestamp::date might be replaced with date(timestamp) like in your case.
Update : If the table contains data with precision upto microseconds, then
SELECT to_char(timestamp,'YYYY-MM-DD HH24:MI'), count(*)
FROM tab
WHERE date(timestamp) = current_date
GROUP BY to_char(timestamp,'YYYY-MM-DD HH24:MI')
might be considered.
Try something like the following:
SELECT DATE_TRUNC('minute', timestamp) as timestamp, COUNT(*) as record
FROM customers
WHERE DATE(timestamp) = CURRENT_DATE
GROUP BY DATE_TRUNC('minute', timestamp)
ORDER BY DATE_TRUNC('minute', timestamp)

Select timestamp range in SQL

I am trying to select a specific time range on a specific days range in SQL postgres. PLease see the code below which gives an error on the '10:00:00'.
The type of data for each columns is :
numeric for "balance",
character varying(255) for "currency",
timestamp without time zone for "created_at" (ex: 2018-03-20 00:00:00).
I tried this link without success.
MySQL select based on daily timestamp range
SELECT SUM(bl.balance) AS balance, bl.currency, bl.created_at
FROM balance_logs bl
WHERE bl.balance_scope = 'system' AND
created_at >= CURRENT_DATE - 2 AND
created_at < CURRENT_DATE AND
created_at BETWEEN '10:00:00' AND '11:00:00'
GROUP BY bl.currency, bl.created_at
ORDER BY created_at DESC
The comparison needs to be as a time:
SELECT SUM(bl.balance) AS balance, bl.currency, bl.created_at
FROM balance_logs bl
WHERE bl.balance_scope = 'system' AND
created_at >= CURRENT_DATE - 2 AND
created_at < CURRENT_DATE AND
created_at::time BETWEEN '10:00:00'::time AND '11:00:00'::time
GROUP BY bl.currency, bl.created_at
ORDER BY created_at DESC;
However, I think it is better to write the WHERE condition as:
extract(hour from created_at) = 10

SELECT to_char(date_col, 'YYYY-MM') from table - doesn't work in subquery

I'm trying to build a query using Postgres 9.5.3
Function to_char in simple statement like this
SELECT to_char(date_created,'YYYY-MM') FROM some_table;
Returns results as follow:
+-----------
| to_char
+-----------
| 2017-06
| 2017-07
| 2017-10
Full statement I want to run
SELECT * FROM generate_series(
to_date('2016-01-01', 'YYYY-MM'),
to_date('2017-01-01', 'YYYY-MM'),
interval '1 month')
AS dates
WHERE dates NOT IN (
SELECT to_char(date_created,'YYYY-MM') FROM some_table
);
Result in the following error
Error in query: ERROR: operator does not exist: timestamp with time zone = text
LINE 2: WHERE dates NOT IN (SELECT to_char(date_create,'YYYY-MM')...
HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts.
You are comparing apples to oranges (timestamps to text).
generate_series() with an interval as the third parameter actually returns a timestamp, not a date. Your sub-select returns the column date_created as a string (text) - and comparing a timestamp to a text doesn't work.
As you apparently only want to check for the same month, you need to convert the date returned from generate_series() to the same text value:
SELECT *
FROM generate_series(to_date('2016-01-01', 'YYYY-MM'),
to_date('2017-01-01', 'YYYY-MM'),
interval '1 month') as dates (d)
WHERE to_char(dates.d, 'yyyy-mm') NOT IN (SELECT to_char(date_created,'YYYY-MM')
FROM some_table);
Another option is to compare dates by "normalizing" the date_created to the start of the month:
SELECT *
FROM generate_series(to_date('2016-01-01', 'YYYY-MM'),
to_date('2017-01-01', 'YYYY-MM'),
interval '1 month') as dates (d)
WHERE dates.d NOT IN (SELECT date_trunc('month', date_created)
FROM some_table);
You have a data type mismatch. Use TO_DATE to convert right side (inner query) back to DATE
...
WHERE dates NOT IN (
SELECT to_date(to_char(date_created,'YYYY-MM'), 'YYYY-MM-DD') FROM some_table
);
or use TO_CHAR to convert left side to CHAR
...
WHERE to_char(dates, 'YYYY-MM')NOT IN (
SELECT to_char(date_created,'YYYY-MM') FROM some_table
);