Observations of the same date between hours with timestamp variable at PostgreSQL - postgresql

I´m trying to run a select to chose some data between hours from the same date. The code below shows the idea, but it isn´t work. My datahora variable is a timestamp in the following format: 'yyyy-mm-dd hh24:mi:ss", as 2023-02-13 15:30:30. How can I run that?
select tr.tick, tr.cot, tr2.cot, tr2.cot-tr.cot as dif
from tb_registros tr
join tb_registros tr2 on to_char(tr.datahora, 'yyyy-mm-dd') = to_char(tr2.datahora, 'yyyy-mm-dd') and to_char(tr.datahora, 'hh24:mi:ss') between '08:55:00' and '08:56:10' and to_char(tr2.datahora, 'hh24:mi:ss') between '09:10:00' and '09:11:10'
where tick = 'ANY'

It's better to operate on proper date/timestamp or time values rather than strings. Assuming the column datahora is really defined as timestamp casting it to a date will remove the time part and casting it to a time value will remove the "day":
select tr.tick, tr.cot, tr2.cot, tr2.cot-tr.cot as dif
from tb_registros tr
join tb_registros tr2
on tr.datahora::date = tr2.datahora::date
and tr.datahora::time between '08:55:00' and '08:56:10'
and tr2.datahora::time between '09:10:00' and '09:11:10'
where tick = 'ANY'
::date is Postgres' proprietary cast operator. If you prefer ANSI SQL, you can use cast(... as date) instead

Related

Add to DATE hour - TSQL

I have a column type time(7).
What i want is to add in time column to date.
i manage to get the only date using GETDATE() function but i fail to add the time part next to date.
Query:
SELECT [Compay]
,[Time]
,CAST(GETDATE() AS DATE) AS Today
,CAST(CAST(GETDATE() AS DATE) AS NVARCHAR) AS Today_AS_Nvarchar
,CAST([Time] AS NVARCHAR) AS Time_AS_Nvarchar
,CAST(CAST(GETDATE() AS DATE) AS NVARCHAR) + ' ' + CAST([Time] AS NVARCHAR) AS Today_Time_AS_Nvarchar
,CONVERT(datetime,CAST(CAST(GETDATE() AS DATE) AS NVARCHAR) + ' ' + CAST([Time] AS NVARCHAR),103)
FROM [Testing_Env].[dbo].[Com_CD_Test]
Error:
Conversion failed when converting date and/or time from character string.
The error arise on CONVERT(datetime,CAST(CAST(GETDATE() AS DATE) AS NVARCHAR) + ' ' + CAST([Time] AS NVARCHAR),103)
is there any easier/orthodox way to achieve it?
You can't add the new date and time data types together like you can the old data types; personally I think this is also better as it stop people treating dates and times like a numerical value.
Assuming you have a date column and a time column you have a few of options. The first is to CAST/CONVERT both to a datetime and then "add" them together. Because the "old" data types work more like numerical values this works, however, you will lose accuracy of your time value if it has a precision of 3 or higher (as datetime is only accurate to 1/300 seconds):
DECLARE #TimeValue time(7) = '17:52:12.1234567',
#DateValue date = '20211016';
SELECT CONVERT(datetime, #DateValue) + CONVERT(datetime, #TimeValue);
If loosing accuracy isn't an option, then you could to use conversion on the date value and use DATEDIFF and DATEADD. For a time(7) you'll want to be using nanoseconds (as microseconds isn't accurate enough). Unfortunately this poses another problem; DATEADD can't handle bigint values (still) and there is no DATEADD_BIG (like there is DATEDIFF_BIG), so this becomes overly complex. You need to first get the difference in milliseconds, and then add the remainder in nanoseconds to still be accurate to 1/1000000 of a second:
DECLARE #TimeValue time(7) = '17:52:12.1234567',
#DateValue date = '20211016';
SELECT DATEADD(NANOSECOND,DATEDIFF_BIG(NANOSECOND,'00:00:00', #TimeValue) % 1000000,DATEADD(MILLISECOND, DATEDIFF_BIG(MILLISECOND,'00:00:00', #TimeValue), CONVERT(datetime2(7),#DateValue)));
Finally, yes, you can convert to values to strings, and then to a datetime2 value; this is probably the easiest methiod. You just need to ensure you use style codes:
DECLARE #TimeValue time(7) = '17:52:12.1234567',
#DateValue date = '20211016';
SELECT CONVERT(datetime2(7),CONVERT(varchar(10), #DateValue, 23) + 'T' + CONVERT(varchar(17), #TimeValue, 114),126);

Converting GMT to CST in postgresql

I am currently working with raw data that have timestamps in GMT and I want to convert them to CST. I am trying to use the cast function to change the timestamp, but it is not working- the times are not affected. Most of what I have read about timezones in postgresql assumes that the default timezone is UTC so I'm not sure if there is a different syntax needed for when the data I'm trying to convert is GMT. Any help is greatly appreciated!
WITH RECURSIVE "child" AS (
SELECT "ConsultantDisplayID",
"JoinDate",
"ParentPersonDisplayID"
FROM "public"."flight_export_consultant"
WHERE "ConsultantDisplayID" = '4019'
UNION
SELECT c."ConsultantDisplayID",
CAST(c."JoinDate" at time zone 'america/chicago' as timestamp) as "JoinDate"
c."ParentPersonDisplayID"
FROM "public"."flight_export_consultant" AS c
JOIN "child" AS cd
ON c."ParentPersonDisplayID" = cd."ConsultantDisplayID"),
"sponsor" AS (
SELECT
"child".*,
c1."ConsultantDisplayID",
Cast(c."JoinDate" at time zone 'america/chicago' as timestamp) as "Sponsor JoinDate"
FROM "public"."flight_export_consultant" AS c1
LEFT JOIN "child"
ON c1."ConsultantDisplayID" = "child"."ParentPersonDisplayID")
SELECT * FROM "sponsor"
As #Mike Organek pointed out a field of type timestamp assumes local time on entry. So first thing you need to establish is where the dates are being entered from and whether they are are actually being entered as GMT. For the moment assuming they are you could do the following:
select 'September 24, 2018, 4:01PM'::timestamp at time zone 'utc' at time zone 'america/chicago';
timezone
---------------------
09/24/2018 11:01:00
-- Or if you want to stick to GMT
select 'September 24, 2018, 4:01PM'::timestamp at time zone 'gmt' at time zone 'america/chicago';
timezone
---------------------
09/24/2018 11:01:00
Basically you are 'anchoring' the timestamp at UTC/GMT and then converting to 'america/chicago'. In other words replicating what a timestamptz field does.
Given that JoinDate is type timestamp, this should be a good workaround for your situation now that we have established that the values in JoinDate of type timestamp represent UTC/GMT timestamps, and your server is not in UTC/GMT. The ideal solution is to use timestamptz columns.
The trick here is to cast JoinDate to text, append a z to it to make it UTC, and then cast it to timestamptz. Once that is done, you can use at time zone 'us/chicago' to do the conversion for you.
WITH RECURSIVE "child" AS (
SELECT "ConsultantDisplayID",
"JoinDate",
"ParentPersonDisplayID"
FROM "public"."flight_export_consultant"
WHERE "ConsultantDisplayID" = '4019'
UNION
SELECT c."ConsultantDisplayID",
"JoinDate",
c."ParentPersonDisplayID"
FROM "public"."flight_export_consultant" AS c
JOIN "child" AS cd
ON c."ParentPersonDisplayID" = cd."ConsultantDisplayID"),
"sponsor" AS (
SELECT
"child".*,
c1."ConsultantDisplayID",
c."JoinDate" as "Sponsor JoinDate"
FROM "public"."flight_export_consultant" AS c1
LEFT JOIN "child"
ON c1."ConsultantDisplayID" = "child"."ParentPersonDisplayID")
SELECT "ConsultantDisplayID",
("JoinDate"::text||'z')::timestamptz at 'america/chicago' as "JoinDate",
"ParentPersonDisplayID",
"ConsultantDisplayID",
("JoinDate"::text||'z')::timestamptz at 'america/chicago' as "Sponsor JoinDate"
FROM "sponsor";

sqlite date comparison

I have column of type date time and values are getting stored in format 10-29-2011 08:25.
I would like to find out the rows only which are less then current date-time. What will be the condition for date comparison for current date and this date-time column field?
Thanks.
you could use the datetime function
SELECT * FROM mytable
WHERE mydate > datetime('now')
you can even make date operations
SELECT * FROM mytable
WHERE mydate > datetime('now','-15 days')

TSQL DateTime Comparison

What I am trying to do is get a result from sql where the dates are in a certain range but its not working correctly, here is my query.
DECLARE #CurrDate DATETIME
SET #CurrDate = GETDATE()
SELECT dbo.ProductDetails.PartnerID
,dbo.ProductDetails.ProductID
,dbo.Products.ProductName
,StartDate
,EndDate
FROM dbo.ProductDetails
INNER JOIN dbo.Products
ON dbo.ProductDetails.ProductID = dbo.Products.ProductID
WHERE CONVERT(VARCHAR(10),StartDate,111) <= #CurrDate
AND CONVERT(VARCHAR(10),EndDate, 111) >= #CurrDate
but when the Enddate = #CurrDate the row does not show, but if i make that date just one day higher it gets displayed. Am i doing anything wrong? Any advice will do, thanks.
GetDate() returns date and time, while your conversion to varchar strips away the time part (I'm suspecting that's all it's actually supposed to do). So you would need to do the same conversion for #CurrDate.
If what you want is to simply consider the date only (ignoring the time part), you could use DATEDIFF instead of converting to varchar (see here); example:
DECLARE #CurrDate DATETIME
SET #CurrDate = GETDATE()
SELECT dbo.ProductDetails.PartnerID, dbo.ProductDetails.ProductID,
dbo.Products.ProductName , StartDate, EndDate
FROM dbo.ProductDetails INNER JOIN
dbo.Products ON dbo.ProductDetails.ProductID = dbo.Products.ProductID
-- where StartDate is on the same day or before CurrDate:
WHERE DATEDIFF(day, StartDate, #CurrDate) >= 0 AND
-- and where EndDate is on the same day or after CurrDate:
DATEDIFF(day, EndDate, #CurrDate) <= 0
If you want only DATE comparison, without time use the
cast(CONVERT(varchar, StartDate, 112) as datetime)
I am quite sure that the comparison takes into account the time as well as the date, in which case if the dates are the same but the current time is greater than the time being compared to you won't get that row as a result.
So, what you need to do is just extract the date part and compare those.
GETDATE() gives you date and time
if yours column have only date
then
CONVERT(VARCHAR(10),StartDate,111) <= #CurrDate
can give you unexpected result
remember
19.12.2011 14:41 > 19.12.2011 00:00
If you are using SQL 2008 or later, and wanting to compare only the date, not the time, you can also do:
Cast(StartDate as Date)
(This avoids having to convert to a string.)

Date range in PostgreSQL

When I apply a date range to my query, is there anyway to display the dates used in the date range even if there is no data at those dates?
Suppose I use,
... where date between '1/12/2010' and '31/12/2010' order by date
What I want in my result is to show sum of all amount column until 1/12/2010 on that day even if there is no data for that date and also same for 31/12/2010.
Join with generate_series() to fill in the gaps.
Example:
CREATE TEMP TABLE foo AS SELECT CURRENT_DATE AS today;
SELECT
COUNT(foo.*),
generate_series::date
FROM
foo
RIGHT JOIN generate_series('2010-12-18', '2010-12-25', interval '1 day') ON generate_series = today
GROUP BY
generate_series;
Result:
0,'2010-12-18'
0,'2010-12-19'
1,'2010-12-20'
0,'2010-12-21'
0,'2010-12-22'
0,'2010-12-23'
0,'2010-12-24'
0,'2010-12-25'