I'm writing Queries on a system someone else installed, so tables can not be changed here.
problem:
I have a table where i've got Date, timeIN and timeOUT
take the following records;
date | timeIN | timerOUT
-------------------------------------------------
2016-01-01 00:00:00.00 | 2000-01-01 07:00 | 2000-01-01 15:00 DATEDIFF = 8H
2016-01-02 00:00:00.00 | 2000-01-01 07:00 | 2000-01-01 15:00 DATEDIFF = 8H
2016-01-05 00:00:00.00 | 2000-01-01 23:00 | 2000-01-01 07:00 DATEDIFF = -16H
How can i get DATEDIFF = 8H from record number 3?
The problem here is that all timeIN and timeOUT stamps have the same dummy date.
You can use CASE expression inside the DATEDIFF function:
SELECT
Diff =
DATEDIFF(
HOUR,
timeIn,
CASE
WHEN timeOut < timeIn THEN DATEADD(DAY, 1, timeOut)
ELSE timeOut
END
)
FROM tbl
This will add one day on timeOut if it's less than the timeIn.
Related
I have a setup where we have
A landing table with a column of type TIMESTAMP_LTZ (consumption_date). Includes the timezone of +02:00
A view (landing_view) that reads from the landing table
A view (raw_data) that reads from a table that has a field of type TIMESTAMP_NTZ (SOURCE_TIMESTAMP), but the value itself is in UTC time.
I have to join the data from landing_view to the data from raw_data using the consumption_date and SOURCE_TIMESTAMP.
SELECT l.ID, l.consumption_date, l.RUN_TIME, r.DISPLAY_NAME, r.source_timestamp, r.value_as_double
FROM "raw_data" r
JOIN "landing_view" l
ON r.SOURCE_TIMESTAMP >= DATEADD(second,120, convert_timezone('UTC',l.consumption_date))
and r.SOURCE_TIMESTAMP < DATEADD(second,1000, convert_timezone('UTC',l.consumption_date))
My problem is that the convert_timezone command does not seem to affect the join clause at all, insted the join is made using the local time included in the LTZ type (+02:00).
If I use the convert_timezone is a select, if works just fine, but for the JOIN it does not.
Is there a way I can tell snowflake to use UTC in the join?
This will depend on what your TIMEZONE setting is. See example below.
If TIMEZONE is UTC:
alter session set TIMEZONE = 'UTC';
select
-- 2AM UTC
'2021-01-02 02:00:00'::timestamp_ntz as SOURCE_TIMESTAMP,
-- 1AM UTC / 12PM Australia/Melbourne time / 1 hour before SOURCE_TIMESTAMP
'2021-01-02 12:00:00 +1100'::timestamp_ltz as CONSUMPTION_DATE,
-- so add one hour to CONSUMPTION_DATE should equal to SOURCE_TIMESTAMP
SOURCE_TIMESTAMP = DATEADD(hour, 1, convert_timezone('UTC', CONSUMPTION_DATE)) as is_equal
;
+-------------------------------+-------------------------------+----------+
| SOURCE_TIMESTAMP | CONSUMPTION_DATE | IS_EQUAL |
|-------------------------------+-------------------------------+----------|
| 2021-01-02 02:00:00.000000000 | 2021-01-02 01:00:00.000 +0000 | True |
+-------------------------------+-------------------------------+----------+
However, if you change your TIMEZONE setting to another timezone, the result will be different:
alter session set TIMEZONE = 'Australia/Melbourne';
select
-- 2AM UTC
'2021-01-02 02:00:00'::timestamp_ntz as SOURCE_TIMESTAMP,
-- 1AM UTC / 12PM Australia/Melbourne time / 1 hour before SOURCE_TIMESTAMP
'2021-01-02 12:00:00 +1100'::timestamp_ltz as CONSUMPTION_DATE,
-- so add one hour to CONSUMPTION_DATE should equal to SOURCE_TIMESTAMP
SOURCE_TIMESTAMP = DATEADD(hour, 1, convert_timezone('UTC', CONSUMPTION_DATE)) as is_equal
;
+-------------------------------+-------------------------------+----------+
| SOURCE_TIMESTAMP | CONSUMPTION_DATE | IS_EQUAL |
|-------------------------------+-------------------------------+----------|
| 2021-01-02 02:00:00.000000000 | 2021-01-02 12:00:00.000 +1100 | False |
+-------------------------------+-------------------------------+----------+
Since you SOURCE_TIMESTAMP stores UTC value, you should change your TIMEZONE setting to match it.
By the way, having CONVERT_TIMEZONE in the DATEADD is redundant, as it only adds extra operation, but not having any effects. See below example:
select
-- 1AM UTC / 9AM Australia/Perth time / 1 hour before SOURCE_TIMESTAMP
'2021-01-02 09:00:00 +0800'::timestamp_ltz as CONSUMPTION_DATE,
DATEADD(hour, 1, CONSUMPTION_DATE) as no_convert_tz,
DATEADD(hour, 1, convert_timezone('UTC', CONSUMPTION_DATE)) as convert_tz,
no_convert_tz = convert_tz
;
+-------------------------------+-------------------------------+-------------------------------+----------------------------+
| CONSUMPTION_DATE | NO_CONVERT_TZ | CONVERT_TZ | NO_CONVERT_TZ = CONVERT_TZ |
|-------------------------------+-------------------------------+-------------------------------+----------------------------|
| 2021-01-02 12:00:00.000 +1100 | 2021-01-02 13:00:00.000 +1100 | 2021-01-02 02:00:00.000 +0000 | True |
+-------------------------------+-------------------------------+-------------------------------+----------------------------+
You can see that the last column returns True.
I am working in a Netezza database that stores time as GMT (or so I am told by our data engineers). I need to be able to convert this to Central Standard Time (CST) but accounting for daylight savings time. I found that I could use something like:
SELECT CURRENT_TIMESTAMP, CURRENT_TIMESTAMP AT TIME ZONE 'CST' AT TIME ZONE 'GMT'
However, when I run this SELECT (keep in mind, today is March 30, 2021 - CST should only be 5 hours different from GTM), I get a 6 hour difference.... I looked up a reference to see what time zones are available in Netezza and I see a "CDT" which is 5 hours, and that works for the 5 hour difference, but this means in my query I would need to either change this each time DST switches over or do some sort of elaborate case statement to know which one to use depending on the date/time of year.
Is there an easy automated way to convert a GTM time to Central Standard Time accounting for daylight savings time? Thanks so much!!!
The question can be interpreted one of two ways. In both cases, the solution is to determine the timezone to convert to, based on whether the timestamp is between 2 AM 2nd Sunday of March and 2 AM on 1st Sunday of Nov (for US Central timezone)
The timestamps in your table, need to be converted to CST or CDT based on the current time (when the query is being run)
this means if the same query was run in Feb, the results would be different than if its run now
also it would be different based on what the timezone of the netezza system is set to
Eg
select
t as original,
-- extract year from current date and 2nd Sunday of March
-- use last_day to make sure we account for March 1 being a Sunday
(next_day(next_day(
last_day((date_part('years', current_date) || '-02-01'):: date),
'sun'),
'sun')|| ' 02:00:00'):: timestamp as dstart,
-- extract year from current date and 1st Sunday of Nov
-- use last_day to make sure we account for Nov 1 being a Sunday
(next_day(last_day(
(date_part('years', current_date) || '-10-01')::date),
'sun')|| ' 02:00:00'):: timestamp as dend,
case when current_timestamp between dstart
and dend then 'CDT' else 'CST' end as tz,
t at time zone tz as converted
from
tdata;
will produce
ORIGINAL | DSTART | DEND | TZ | CONVERTED
---------------------+---------------------+---------------------+-----+------------------------
2021-01-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2021-01-01 12:00:00-05
2021-04-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2021-04-01 12:00:00-05
2020-04-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2020-04-01 12:00:00-05
2020-12-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2020-12-01 12:00:00-05
(4 rows)
OR
The timestamps in your table need to be converted to CST or CDT depending on when the daylight savings started/ended in the respective year as defined in the time stamp.
this is more deterministic
select
t as original,
-- extract year from this timestamp and 2nd Sunday of March
-- use last_day to make sure we account for March 1 being a Sunday
(next_day(next_day(
last_day((date_part('years', t) || '-02-01'):: date), 'sun'),
'sun')|| ' 02:00:00'):: timestamp as dstart,
-- extract year from this timestamp and 1st Sunday of Nov
-- use last_day to make sure we account for Nov 1 being a Sunday
(next_day(last_day((date_part('years', t) || '-10-01')::date),
'sun')|| ' 02:00:00'):: timestamp as dend,
case when current_timestamp between dstart
and dend then 'CDT' else 'CST' end as tz,
t at time zone tz as converted
from
tdata;
This will produce (tdata is a sample table w/ 4 timestamps)
ORIGINAL | DSTART | DEND | TZ | CONVERTED
---------------------+---------------------+---------------------+-----+------------------------
2021-01-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CST | 2021-01-01 11:00:00-06
2021-04-01 17:00:00 | 2021-03-14 02:00:00 | 2021-11-07 02:00:00 | CDT | 2021-04-01 12:00:00-05
2020-04-01 17:00:00 | 2020-03-08 02:00:00 | 2020-11-01 02:00:00 | CDT | 2020-04-01 12:00:00-05
2020-12-01 17:00:00 | 2020-03-08 02:00:00 | 2020-11-01 02:00:00 | CST | 2020-12-01 11:00:00-06
(4 rows)
system.admin(admin)=> select '2021-04-07 11:00:00' as gmt, timezone('2021-04-07 11:00:00' , 'GMT', 'America/New_York') as eastern, timezone('2021-04-07 11:00:00', 'GMT', 'America/Chicago') as central, timezone('2021-04-07 11:00:00', 'GMT', 'America/Los_Angeles') as pacific;
gmt | eastern | central | pacific
---------------------+---------------------+---------------------+---------------------
2021-04-07 11:00:00 | 2021-04-07 07:00:00 | 2021-04-07 06:00:00 | 2021-04-07 04:00:00
(1 row)
system.admin(admin)=> select '2021-03-07 11:00:00' as gmt, timezone('2021-03-07 11:00:00' , 'GMT', 'America/New_York') as eastern, timezone('2021-03-07 11:00:00', 'GMT', 'America/Chicago') as central, timezone('2021-03-07 11:00:00', 'GMT', 'America/Los_Angeles') as pacific;
gmt | eastern | central | pacific
---------------------+---------------------+---------------------+---------------------
2021-03-07 11:00:00 | 2021-03-07 06:00:00 | 2021-03-07 05:00:00 | 2021-03-07 03:00:00
(1 row)
Instead of CDT and CST if we use 'America/Chicago' as shown above it takes care of daylight savings.
I have a scheduled job that runs daily ( in the morning or evening, or the next day in the morning) that sends some reports to an FTP.
I want to include in the report only records from the current year.
And if it is 1st of january of the next year, in the morning, I want to show all the records from the past year.
If it is 1st of january in the evening, and I have records from the new year, I want to include only those records from the new year
Example:
transfer date | job run date | Records with year
-----------------|------------------|------------------
30.12.2018 08:00 | 30.12.2018 19:00 | 2018
30.12.2018 08:00 | 31.12.2018 02:00 | 2018
31:12.2018 08:00 | 31.12.2018 19:00 | 2018
31.12.2018 08:00 | 01.01.2019 01:00 | 2018
01.01.2019 08:00 | 01.01.2019 19:00 | 2019
01.01.2019 08:00 | 02.01.2019 01:00 | 2019
In the last column is the record's year that i want
I would like a simple solution, so that the original query is not transformed into a function or stored procedure etc.
What have I tried:
SELECT
DateReceived ,
UniqueNumber ,
TransferDate ,
CompanyCode
FROM
ExportData
where
YEAR(convert(datetime,TransferDate)) =
case
when year(convert(datetime,Transferdate))=year(getdate())
and month(getdate()) =1
and day(getdate()) =1
then year(getdate())
when Year(convert(datetime,transferdate))=year(getdate())-1
then year(getdate())-1
end
order by
TransferDate DESC
Can you please check this simple adjustment in WHERE condition works for you or not. This will only return records for the Maximum YEAR available in the table.
SELECT
DateReceived ,
UniqueNumber ,
TransferDate ,
CompanyCode
FROM
ExportData
WHERE YEAR(CONVERT(DATETIME, TransferDate)) =
(
SELECT YEAR(MAX(CONVERT(DATETIME, TransferDate)))
FROM TransferDate
)
ORDER BY TransferDate DESC;
Using T-SQL, I want a new column that will show me the first day of each month, for the current year of getdate().
After that I need to count the rows on this specific date. Should I do it with CTE or a temp table?
If 2012+, you can use DateFromParts()
To Get a List of Dates
Select D = DateFromParts(Year(GetDate()),N,1)
From (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) N(N)
Returns
D
2017-01-01
2017-02-01
2017-03-01
2017-04-01
2017-05-01
2017-06-01
2017-07-01
2017-08-01
2017-09-01
2017-10-01
2017-11-01
2017-12-01
Edit For Trans Count
To get Transactions (assuming by month). It becomes a small matter of a left join to created Dates
-- This is Just a Sample Table Variable for Demonstration.
-- Remove this and Use your actual Transaction Table
--------------------------------------------------------------
Declare #Transactions table (TransDate date,MoreFields int)
Insert Into #Transactions values
('2017-02-18',6)
,('2017-02-19',9)
,('2017-03-05',5)
Select TransMonth = A.MthBeg
,TransCount = count(B.TransDate)
From (
Select MthBeg = DateFromParts(Year(GetDate()),N,1)
,MthEnd = EOMonth(DateFromParts(Year(GetDate()),N,1))
From (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12)) N(N)
) A
Left Join #Transactions B on TransDate between MthBeg and MthEnd
Group By A.MthBeg
Returns
TransMonth TransCount
2017-01-01 0
2017-02-01 2
2017-03-01 1
2017-04-01 0
2017-05-01 0
2017-06-01 0
2017-07-01 0
2017-08-01 0
2017-09-01 0
2017-10-01 0
2017-11-01 0
2017-12-01 0
For an adhoc table of months for a given year:
declare #year date = dateadd(year,datediff(year,0,getdate() ),0)
;with Months as (
select
MonthStart=dateadd(month,n,#year)
from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11)) t(n)
)
select MonthStart
from Months
rextester demo: http://rextester.com/POKPM51023
returns:
+------------+
| MonthStart |
+------------+
| 2017-01-01 |
| 2017-02-01 |
| 2017-03-01 |
| 2017-04-01 |
| 2017-05-01 |
| 2017-06-01 |
| 2017-07-01 |
| 2017-08-01 |
| 2017-09-01 |
| 2017-10-01 |
| 2017-11-01 |
| 2017-12-01 |
+------------+
The first part: dateadd(year,datediff(year,0,getdate() ),0) adds the number of years since 1900-01-01 to the date 1900-01-01. So it will return the first date of the year. You can also swap year for other levels of truncation: year, quarter, month, day, hour, minute, second, et cetera.
The second part uses a common table expression and the table value constructor (values (...),(...)) to source numbers 0-11, which are added as months to the start of the year.
Not sure why you require recursive... But for first day of month you can try query like below:
Select Dateadd(day,1,eomonth(Dateadd(month, -1,getdate())))
declare #year date = dateadd(year,datediff(year,0,getdate() ),0)
;WITH months(MonthNumber) AS
(
SELECT 0
UNION ALL
SELECT MonthNumber+1
FROM months
WHERE MonthNumber < 11
)
select dateadd(month,MonthNumber,#year)
from months
When two tables are given
Employee Table
EmpID Name
1 Jon
2 Smith
3 Dana
4 Nancy
Lab Table
EmpID StartTime EndTime Date LabID
1 10:00 AM 12:15 PM 01/JAN/2000 Lab I
1 11:00 AM 14:15 PM 01/JAN/2000 Lab II
1 16:30 PM 18:30 PM 01/JAN/2000 Lab I
2 10:00 AM 12:10 PM 01/JAN/2000 Lab I
From the given details ,I have to find out the overlapping hours,and non overlapping hours of each employee on each date. (StartTime and EndTime are of type varchar).
The expected output is
-------------------------------------------------------------------------------
EmpID| Name| Overlapping | Non-Overlapping | Date
Period Period
-------------------------------------------------------------------------------
1 Jon | 10:00 AM to 12:15 PM |16:30 PM to 18:30 PM | 01/JAN/2000
| AND | |
| 11:00 AM to 14:15 PM | |
| AND ...(If any) | |
--------------------------------------------------------------------------------
2 Smith| NULL | 10:00 AM to 12:10 PM |01/JAN/2000
--------------------------------------------------------------------------------
Please help me to bring such output using TSQL(SQL Server 2005/2008).
First, you should probably consider using a DateTime field to store the StartTime and EndTime, and thus make calculations easier, and remove the need for the Date field.
SELECT t1.EmpID,
t1.StartTime,
t1.EndTime,
t2.StartTime
t2.EndTime,
FROM lab t1
LEFT OUTER JOIN lab t2
ON t2.StartTime BETWEEN t1.StartTime AND t1.EndTime
AND t2.EmpID = t1.EmpID
ORDER BY t1.EmpID,
t1.StartTime,
t2.StartTime
That won't get you the EXACT format you have listed, but it's close. You should end up with:
| EmpID| Name| Normal Period | Overlapping Period |
------------------------------------------------------------
| 1 | Jon | 10:00 AM | 12:15 PM | 11:00 AM | 02:15 PM |
------------------------------------------------------------
| 2 | Smith | 10:00 AM | 12:10 PM | NULL | NULL |
------------------------------------------------------------
Each overlapped period within a normal period would show up in a new row, but any period with no overlaps would have only one row. You could easily concatenate the fields if you wanted specifically the "xx:xx xx to xx:xx xx" format. Hope this helps you some.