Timestamp in Between Join SQL Server - sql-server

How do I join Table B on Table A where Table B has timestamps in-between Table A's timestamps? I am using SQL Server 2008.
Table A
Start End
---------------------------------------
2022-04-29 15:00:00 2022-04-29 15:30:00
2022-04-29 15:30:00 2022-04-29 17:00:00
2022-04-29 17:00:00 2022-04-29 18:00:00
2022-04-29 18:00:00 2022-04-29 18:30:00
2022-04-29 18:30:00 2022-04-29 20:00:00
Table B
Start Value
-----------------------
2022-04-29 12:00:00 100
2022-04-29 15:30:00 200
2022-04-29 16:00:00 300
2022-04-29 18:00:00 400
2022-04-29 21:00:00 500
Desired result - product of Table A and B:
Start End Value
--------------------------------------------
2022-04-29 15:00:00 2022-04-29 15:30:00 200
2022-04-29 15:30:00 2022-04-29 17:00:00 300
2022-04-29 17:00:00 2022-04-29 18:00:00 NaN
2022-04-29 18:00:00 2022-04-29 18:30:00 400
2022-04-29 18:30:00 2022-04-29 20:00:00 NaN

You really need to decide on whether or not the top ranges are inclusive or not (see Larnu's comment) >= and < will generate different results than > and <=
Select A.*
,B.Value
From TableA A
Left Join TableB B on B.Start >= A.Start
and B.Start < A.[End]
Results

Related

Netezza Convert UTC/GMT to Central with Daylight Savings Time

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.

SQL Server - Join results of one query to first matching result from second query

I want to join the results of paycheck_detail query with the results of timesheet query, joining on employeeId. Each employee will have one paycheck record per pay period that needs to join to the first matching timesheet record in order to fill a pdf form.
Query 1
SELECT employeeId, workday, hours FROM timesheet WHERE weekEndingDate = '2019-01-19'
employeeId workday hours
------------ ------------ -------
25 2019-01-18 2.68
25 2019-01-18 4.05
25 2019-01-18 2.75
29 2019-01-18 3.25
29 2019-01-18 4
29 2019-01-18 2.75
Query 2
SELECT * FROM paycheck_detail WHERE weekEndingDate = '2019-01-19'
employeeId weekendingdate fica federal local state checkNumber
------------ ---------------- ------- --------- ------- ------- -------------
29 2019-01-19 26.06 19.00 3.41 10.46 13325
25 2019-01-19 47.00 19.20 5.60 11.20 13326
Desired result
employeeId workday hours fica federal local state checkNumber
------------ ------------ ------- ------- --------- ------- ------- ------------- --
25 2019-01-18 2.68 47.00 19.20 5.60 11.20 13326
25 2019-01-18 4.05
25 2019-01-18 2.75
29 2019-01-18 3.25 26.06 19.00 3.41 10.46 13325
29 2019-01-18 4
29 2019-01-18 2.75

First TimeIn Last TimeOut for each employee for respective days

I have following table from which I want to extract the time calculated. I am looking to get the Hours Spent by each employee for each day.
CREATE TABLE Attendance
(
, EmpID INT
, TimeIn datetime
, TimeOut datetime
)
The sample record against this table I have is listed below.
EmpID | AttendanceTimeIN | AttendanceTimeOut
1 2017-04-01 9:00:00 2017-04-01 10:20:00
2 2017-04-01 9:00:00 2017-04-01 12:30:00
1 2017-04-01 10:25:00 2017-04-01 17:30:00
2 2017-04-01 13:26:00 2017-04-01 14:50:00
2 2017-04-01 15:00:00 2017-04-01 18:00:00
1 2017-04-02 9:00:00 2017-04-02 11:00:00
1 2017-04-02 11:10:00 2017-04-02 12:00:00
2 2017-04-02 9:00:00 2017-04-02 12:00:00
1 2017-04-02 12:50:00 2017-04-02 18:00:00
2 2017-04-02 12:51:00 2017-04-02 18:00:00
I want to get the First TimeIn and Last TimeOut of and employee for each day to calculate how many hours a specific employee have spent in office each day.
I'm bit confused that how to use Min/Max function so I can get both employees hours for each day.
The result set I am looking for should look like this.
EmpID | AttendanceTimeIN | AttendanceTimeOut
1 2017-04-01 9:00:00 2017-04-01 17:30:00
2 2017-04-01 9:00:00 2017-04-01 18:00:00
1 2017-04-02 9:00:00 2017-04-02 18:00:00
2 2017-04-02 9:00:00 2017-04-02 18:00:00
Any help would be highly appreciated.
Thank you
If your TimeIn and TimeOut are datetime type (which they should be!), this solution works with the tests I did:
SELECT
EmpID
, MIN(TimeIn)
, MAX(TimeOut)
FROM Attendance
GROUP BY EmpID, CAST(TimeIn AS DATE)
the GROUP BY clause means that there's one row for each employee and each day, since CASTing to DATE gets rid of the time part. MIN and MAX then just inherently work.

sql server combining date_time and smallint columns to derive datetime column in 12 hour format

I have a date_time column and hour_ending column,like below. How do i join them both together to derive a date_time column in 12 hour date format. my requirement is to join Table A with Table B using date_time as join key
TABLE A
DATE HOUR_ENDING
--- ----------
8/31/2016 12:00:00.000 AM 1
8/31/2016 12:00:00.000 AM 2
8/31/2016 12:00:00.000 AM 3
8/31/2016 12:00:00.000 AM 4
8/31/2016 12:00:00.000 AM 5
8/31/2016 12:00:00.000 AM 6
8/31/2016 12:00:00.000 AM 7
8/31/2016 12:00:00.000 AM 8
8/31/2016 12:00:00.000 AM 9
8/31/2016 12:00:00.000 AM 10
8/31/2016 12:00:00.000 AM 11
8/31/2016 12:00:00.000 AM 12
8/31/2016 12:00:00.000 AM 13
8/31/2016 12:00:00.000 AM 14
8/31/2016 12:00:00.000 AM 15
8/31/2016 12:00:00.000 AM 16
8/31/2016 12:00:00.000 AM 17
8/31/2016 12:00:00.000 AM 18
8/31/2016 12:00:00.000 AM 19
8/31/2016 12:00:00.000 AM 20
8/31/2016 12:00:00.000 AM 21
8/31/2016 12:00:00.000 AM 22
8/31/2016 12:00:00.000 AM 23
8/31/2016 12:00:00.000 AM 24
Table B (I need Table A to be like this)
8/31/2013 12:00:00 AM
8/31/2013 1:00:00 AM
8/31/2013 2:00:00 AM
8/31/2013 3:00:00 AM
8/31/2013 4:00:00 AM
8/31/2013 5:00:00 AM
8/31/2013 6:00:00 AM
8/31/2013 7:00:00 AM
8/31/2013 8:00:00 AM
8/31/2013 9:00:00 AM
8/31/2013 10:00:00 AM
8/31/2013 11:00:00 AM
8/31/2013 12:00:00 PM
8/31/2013 1:00:00 PM
8/31/2013 2:00:00 PM
8/31/2013 3:00:00 PM
8/31/2013 4:00:00 PM
8/31/2013 5:00:00 PM
8/31/2013 6:00:00 PM
8/31/2013 7:00:00 PM
8/31/2013 8:00:00 PM
8/31/2013 9:00:00 PM
8/31/2013 10:00:00 PM
8/31/2013 11:00:00 PM
9/1/2013 12:00:00 AM
You can use DATEADD() to adjust the dates from the A table using the hour offsets. Then, join table A to B using this adjusted timestamp.
SELECT *
FROM tableA a
INNER JOIN tableB b
ON DATEADD(HOUR, a.HOUR_ENDING, a.DATE) = b.DATE
By the way you should consider changing your table A design such that date and time are being stored together in a single column.

Data according to date in MSSQL

I have a data like this
RID Region StartDate EndDate
944 Canada 2016-01-09 00:00:00.000 2016-01-16 23:59:59.000
955 Canada 2016-01-17 00:00:00.000 2016-01-24 23:59:59.000
981 Canada 2016-02-01 00:00:00.000 2016-02-08 23:59:59.000
996 Canada 2016-02-09 00:00:00.000 2016-02-16 23:59:59.000
1006 Canada 2016-01-25 00:00:00.000 2016-01-31 23:59:59.000
1020 Canada 2016-02-17 00:00:00.000 2016-02-24 23:59:59.000
1030 Canada 2016-02-25 00:00:00.000 2016-02-29 23:59:59.000
1041 Canada 2016-03-01 00:00:00.000 2016-03-08 23:59:59.000
1046 Canada 2016-03-09 00:00:00.000 2016-03-16 23:59:59.000
1062 Canada 2016-03-17 00:00:00.000 2016-03-24 23:59:59.000
1073 Canada 2016-03-24 00:00:00.000 2016-03-31 23:59:59.000
1083 Canada 2016-04-01 00:00:00.000 2016-04-08 23:59:59.000
1105 Canada 2016-04-09 00:00:00.000 2016-04-16 23:59:59.000
1118 Canada 2016-04-17 00:00:00.000 2016-04-24 23:59:59.000
1128 Canada 2016-04-25 00:00:00.000 2016-04-30 23:59:59.000
1164 Canada 2016-05-01 00:00:00.000 2016-05-08 23:59:59.000
now i try to select data like this
select * from tab1 where Region='Canada'
and StartDate ='2016-01-09 00:00:00.000'
and EndDate ='2016-01-24 23:59:59.000'
desired result is
RID Region StartDate EndDate
944 Canada 2016-01-09 00:00:00.000 2016-01-16 23:59:59.000
955 Canada 2016-01-17 00:00:00.000 2016-01-24 23:59:59.000
but when i execute this query data is empty
any solution?
I think you were intending to restrict to a date range, but you actually restricted to two points in time instead. Try this query:
SELECT *
FROM tab1
WHERE Region = 'Canada' AND
StartDate >= '2016-01-09 00:00:00.000' AND
EndDate <= '2016-01-24 23:59:59.000'
Try this.
SELECT *
FROM tab1
WHERE Region = 'Canada'
AND StartDate >='2016-01-09 00:00:00.000'
AND EndDate <='2016-01-24 23:59:59.000'
The 'between' must work. I tried this. If in case it is not working, try convert function for those datetime columns.
SELECT *
FROM tab1
WHERE Region = 'Canada' AND
StartDate >= convert(datetime,'2016-01-09 00:00:00.000') AND
EndDate <= convert(datetime,'2016-01-24 23:59:59.000')

Resources