I am trying to run a simple query which gets me data based on timestamp, as follows:
SELECT *
FROM <table_name>
WHERE id = 1
AND usagetime = timestamp('2012-09-03 08:03:06')
WITH UR;
This does not seem to return a record to me, whereas this record is present in the database for id = 1.
What am I doing wrong here?
The datatype of the column usagetime is correct, set to timestamp.
#bhamby is correct. By leaving the microseconds off of your timestamp value, your query would only match on a usagetime of 2012-09-03 08:03:06.000000
If you don't have the complete timestamp value captured from a previous query, you can specify a ranged predicate that will match on any microsecond value for that time:
...WHERE id = 1 AND usagetime BETWEEN '2012-09-03 08:03:06' AND '2012-09-03 08:03:07'
or
...WHERE id = 1 AND usagetime >= '2012-09-03 08:03:06'
AND usagetime < '2012-09-03 08:03:07'
You might want to use TRUNC function on your column when comparing with string format, so it compares only till seconds, not milliseconds.
SELECT * FROM <table_name> WHERE id = 1
AND TRUNC(usagetime, 'SS') = '2012-09-03 08:03:06';
If you wanted to truncate upto minutes, hours, etc. that is also possible, just use appropriate notation instead of 'SS':
hour ('HH'), minute('MI'), year('YEAR' or 'YYYY'), month('MONTH' or 'MM'), Day ('DD')
Related
I am trying to write a SQL query where the results would show the first value (ID) per user per day for the last year.
I tried using the query below and am able to get results for one day but when I try to change the time range to > 2021-06-01, it does not give me the results I expect.
select * from table
where value in
(
SELECT min(value)
FROM table
WHERE valueid = x
group by user
) and Time = '2022-05-30' and value is not null
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().
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'
In my table I have the following scheme:
id - integer | date - text | name - text | count - integer
I want just to count some actions.
I want put 1 when date = '30-04-2019' not exist yet.
I want put +1 when is row already exist.
My idea is:
UPDATE "call" SET count = (1 + (SELECT count
FROM "call"
WHERE date = '30-04-2019'))
WHERE date = '30-04-2019'
But it is not working when row doesn't exist.
It is possible without some extra triggers, etc...
You can use a writeable CTE to achieve this. Additionally the UPDATE statement can be simplified to a simple set count = count + 1 there is no need for a sub-select.
with updated as (
update "call"
set count = count + 1
where date = '30-04-2019'
returning id
)
insert into "call" (date, count)
select '30-04-2019', 1
where not exists (select *
form updated);
If the update did not find a row, the where not exists condition will be true and the insert will be executed.
Note that the above is not safe for concurrent execution from multiple transactions. If you want to make this safe, create a unique index on the date column. Then use an INSERT ... ON CONFLICT instead:
insert into "call" (date, count)
values ('30-04-2019', 1)
on conflict (date)
do update
set count = "call".count + 1;
Again: the above requires a unique index (or constraint) on the date column.
Unrelated to the immediate problem, but: storing dates in a text column is a really, really bad idea. You should change your table definition and change the data type for the "date" column to date.
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