How to query by date and time in postgresql - postgresql

i have a table where my date/time is of form: 2020-03-10 22:54:08
This is a timestampped object. I tried the following query but didn't return any rows:
select ts from table1
where cast(ts as timestamp) = '2020-03-10 22:54:08'
returns nothing.
How do i query based on date and time in postgressql?

A timestamp has microsecond resolution, so you have to use same techiques as when testing floating point numbers: Round it or use only < and > for comparison.

To retrieve data from a database, you need to refer to SQL SELECT syntax. In your situation, the ts column is already a timestamp, so there is no need to use cast(). Bear in mind, however, that a timestamp type contains fractions of a second (i.e., 2020-03-10 22:54:03.xxx), so you would be better off using a comparison operator (>,<,>=,or <=)
You can retrieve all columns by using the * syntax:
select *
from my_table
where ts >= '2020-03-10 22:54:08';

tymestamp type by default contains also microseconds, so, now() which, for example, is 2020-03-11 01:56:27.593985 here obviously is not equal to 2020-03-11 01:56:27. If you do not want to have microseconds precision in your data then declare your field like ts timestamp(0) NOT NULL DEFAULT now() which means "0 decimal digits for microseconds":
select
current_timestamp::timestamp as ts,
current_timestamp::timestamp(2) as ts2,
current_timestamp::timestamp(0) as ts0;
ts | ts2 | ts0
---------------------------+------------------------+---------------------
2020-03-11 02:02:52.98298 | 2020-03-11 02:02:52.98 | 2020-03-11 02:02:53

Actually this worked.
select distinct(ts) from my_table where ts >= '2020-03-10 22:54:08' and ts <= '2020-03-10 22:54:09'
But this doesn't give me the whole rows
But then i tried this and this worked:
select ts from table1
where to_char(ts,'YYYY-MM-DD HH24:MI:SS') = '2020-03-10 22:54:08'

Related

How to get the latest value of a time duration (let's say for 1 minute) in Kusto table

I want to find the latest value of a column for particular time duration(1 minute in my case) from Kusto table.
I have timeseries data in PostgreSQL table and I am using last() function (https://docs.timescale.com/api/latest/hyperfunctions/last/)to find the latest value of scaled_value for 1 minute time bucket of PostgreSQL and I want to use same function in Kusto Table to get the latest value of scaled_value . What will be correct function to use in Kusto corresponding to last() function in Postgresql
Code I am using in PostgreSQL :
SELECT CAST(EXTRACT(EPOCH FROM time_bucket('1 minutes', timestamp) AT TIME ZONE 'UTC') * 1000 AS BIGINT) as timestamp_epoch,
vessel_telemetry.timeSeries,
last(vessel_telemetry.scaled_value, vessel_telemetry.timestamp) as scaled_value,
FROM shipping.vessel_telemetry
WHERE vessel_telemetry.ingested_timestamp >= '2022-07-20T10:10:58.71Z' AND vessel_telemetry.ingested_timestamp < '2022-07-20T10:15:33.703985Z'
GROUP BY time_bucket('1 minutes', vessel_telemetry.timestamp), vessel_telemetry.vessel_timeSeries
Corresponding code I am using in ADX
VesselTelemetry_DS
| where ingested_timestamp >= datetime(2022-07-20T10:10:58.71Z) and ingested_timestamp < datetime(2022-07-20T10:15:33.703985Z)
| summarize max_scaled_value = max(scaled_value) by bin(timestamp, 1m), timeSeries
| project timestamp_epoch =(datetime_diff('second', timestamp, datetime(1970-01-01)))*1000, timeSeries, max_scaled_value
The data that i am getting using PostgreSQL is not matching with the data I am getting from ADX Query. I think the functionality of last() function of Postgre is different from max() function of ADX. Is there any function in ADX that we can use to perform same as last() of PSQL
arg_max()
arg_max (ExprToMaximize, * | ExprToReturn [, ...])
Please note the order of the parameters, which is opposite to Timescale's last() -
First the expression to maximize, in your case timestamp and then the expression(s) to return, in your case scaled_value

Select one record per minute group in postgres

I have a big table in a postgres db with location of units. Now I need to retrieve a location for every 60 seconds.
In Mysql, this is a piece of cake: select * from location_table where unit_id = '123' GROUP BY round(timestamp / 60)
But in postgres this seems to be a very hard problem. I also have the timestamps in dateformat rather than in epoch format.
Here is an example of how the table looks
CREATE TABLE location_table (
unit_id int,
"timestamp" timestamp(3) without time zone NOT NULL,
lat double precision,
lng double precision
);
Use date_trunc() to make sets per minute:
SELECT * -- most likely not what you want
FROM location_table
WHERE unit_id = 123 -- numbers don't need quotes '
GROUP BY date_trunc('minute', 'timestamp');
The * is of course wrong, but I don't know what you want to know about the GROUP so I can't come up with something better.
Edit:
When you need a random result from your table, DISTINCT ON () could do the job:
SELECT DISTINCT ON(date_trunc('minute', timestamp))
* -- your columns
FROM location_table;
There are other (standard SQL) solutions as well, like using row_number().

How toConvert minutes into hours in postgresql

I'm new in PostgreSQL I need to convert the minute's value in a column into hours and minutes format I have searched in various sources but failed to achive.Some one please help me to achieve this.
In mean while I try to use to_char() as follows :
UPDATE tablename SET col2 = TO_CHAR(((col1*60 ||`second`))::interval, ‘HH24:MI:SS’) where id = 145;
but I get the following error...
column "late_by" is of type timestamp with time zone but expression is of type text
LINE 2: UPDATE attendance SET late_by = TO_CHAR(((lateby*60 || 'seco...
^
HINT: You will need to rewrite or cast the expression.
It is unclear what type each column in your statement is.
But if it helps, you can perform maths on intervals
select interval '60 seconds' * 15;
or in your case, if "col1" is integer: interval '60 seconds' * col1;
your column late_by is of time timestamp, yet you want to update it with interval, not timestamp. If you want to save how much time somebody is late, better use interval, eg:
t=# create table w3 (t interval);
CREATE TABLE
t=# insert into w3 select (185||' seconds')::interval;
INSERT 0 1
t=# select * from w3;
t
----------
00:03:05
(1 row)
as you can see "conversion" to minutes done by postgres itself

Extract year from date within WHERE clause

I need to include EXTRACT() function within WHERE clause as follow:
SELECT * FROM my_table WHERE EXTRACT(YEAR FROM date) = '2014';
I get a message like this:
pg_catalog.date_part(unknown, text) doesn't exist**
SQL State 42883
Here is my_table content (gid INTEGER, date DATE):
gid | date
-------+-------------
1 | 2014-12-12
2 | 2014-12-08
3 | 2013-17-15
I have to do it this way because the query is sent from a form on a website that includes a 'Year' field where users enter the year on a 4-digits basis.
The problem is that your column is of data type text, while EXTRACT() only works for date / time types.
You should convert your column to the appropriate data type.
ALTER TABLE my_table ALTER COLUMN date TYPE date;
That's smaller (4 bytes instead of 11 for the text), faster and cleaner (disallows illegal dates and most typos).
If you have non-standard format add a USING clause with a conversion expression. Example:
Alter character field to date
Also, for your queries to be fast with a plain index on date you should rather use sargable predicates. Like:
SELECT * FROM my_table
WHERE date >= '2014-01-01'
AND date < '2015-01-01';
Or, to go with your 4-digit input for the year:
SELECT * FROM my_table
WHERE date >= to_date('2014', 'YYYY')
AND date < to_date('2015', 'YYYY');
You could also be more explicit:
to_date('2014' || '0101', 'YYYYMMNDD')
Both produce the same date '2014-01-01'.
Aside: date is a reserved word in standard SQL and a basic type name in Postgres. Don't use it as identifier.
This happens because the column has a text or varchar type, as opposed to date or timestamp. This is easily reproducible:
SELECT 1 WHERE extract(year from '2014-01-01'::text)='2014';
yields this error:
ERROR: function pg_catalog.date_part(unknown, text) does not exist
LINE 1: SELECT 1 WHERE extract(year from '2014-01-01'::text)='2014';
^ HINT: No function matches the given name and argument types. You might need to add explicit type casts.
extract or is underlying function date_part does not exist for text-like datatypes, but they're not needed anyway. Extracting the year from this date format is equivalent to getting the 4 first characters, so your query would be:
SELECT * FROM my_table WHERE left(date,4)='2014';

SUBSTR does not work with datatype "timestamp" in Postgres 8.3

I have a problem with the query below in postgres
SELECT u.username,l.description,l.ip,SUBSTRING(l.createdate,0,11) as createdate,l.action
FROM n_logs AS l LEFT JOIN n_users AS u ON u.id = l.userid
WHERE SUBSTRING(l.createdate,0,11) >= '2009-06-07'
AND SUBSTRING(l.createdate,0,11) <= '2009-07-07';
I always used the above query in an older version of postgres and it worked 100%. Now with the new version of posgres it gives me errors like below
**ERROR: function pg_catalog.substring(timestamp without time zone, integer, integer) does not exist
LINE 1: SELECT u.username,l.description,l.ip,SUBSTRING(l.createdate,...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.**
I assume it has something to do with datatypes, that the data is a time zone and that substring only support string datatypes, now my question is what can I do about my query so that my results would come up?
The explicit solution to your problem is to cast the datetime to string.
...,SUBSTRING(l.createdate::varchar,...
Now, this isn't at all a good practice to use the result to compare dates.
So, the good solution to your need is to change your query using the explicit datetime manipulation, comparison and formatting functions, like extract() and to_char()
You'd have to change your query to have a clause like
l.createdate::DATE >= '2009-06-07'::DATE
AND l.createdate::DATE < '2009-07-08'::DATE;
or one of the alternatives below (which you should really accept instead of this.)
SELECT u.username, l.description, l.ip,
CAST(l.createdate AS DATE) as createdate,
l.action
FROM n_logs AS l
LEFT JOIN
n_users AS u
ON u.id = l.userid
WHERE l.createdate >= '2009-06-07'::TIMESTAMP
AND l.createdate < '2009-07-07'::TIMESTAMP + '1 DAY'::INTERVAL
I'm not sure what you want to achieve, but basically "substring" on date datatypes is not really well defined, as it depends on external format of said data.
In most of the cases you should use extract() or to_char() functions.
Generally - for returning data you want to_char(), and for operations on it (including comparison) - extract(). There are some cases where this general rule does not apply, but these are usually signs of not really well thought data-structure.
Example:
# select to_char( now(), 'YYYY-MM-DD');
to_char
------------
2009-07-07
(1 row)
For extract let's write a simple query that will list all objects created after 8pm:
select * from objects where extract(hour from created) >= 20;
A variation on the Quassnoi's answer:
SELECT
u.username,
l.description,
l.ip,
CAST(l.createdate AS DATE) as createdate,
l.action
FROM
n_logs AS l
LEFT JOIN
n_users AS u
ON
(u.id = l.userid)
WHERE
l.createdate::DATE BETWEEN '2009-06-07'::DATE AND '2009-07-07'::DATE
If you use Postgresql, you will receive:
select('SUBSTRING(offer.date_closed, 0, 11)')
function substr(timestamp without time zone integer integer) does not
exist
Use:
select('SUBSTRING(CONCAT(offer.date_closed, \'\'), 0, 11)')