how to get before and after date from the given date? - sql-server

I have a table as below,
empno
date
1
2022-08-20 00:00:00
1
2022-08-19 00:00:00
1
2022-08-18 00:00:00
1
2022-08-17 00:00:00
If the date is 2022-08-22 I want to get 2022-08-20 00:00:00 as my output. How can I get this?
Thank you.

Related

postgresql frequency adjustment and data filling

I have a table in PostgreSQL
time
goals
assists
2022-03-01 00:00:00
22
1
2022-03-03 00:00:00
24
2
2022-03-07 00:00:00
25
3
I want to add missing timestamps and fill the goals and assists in, as displayed in the table below
time
goals
assists
2022-03-01 00:00:00
22
1
2022-03-02 00:00:00
22
1
2022-03-03 00:00:00
24
2
2022-03-04 00:00:00
24
2
2022-03-05 00:00:00
24
2
2022-03-06 00:00:00
24
2
2022-03-07 00:00:00
25
3

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.

Get results from past year if 1st of january

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;

SSRS - Using specific Row Number

I have a SQL query where I am getting the row number for a count of employees per division and per month at the beginning of the month and the end of the month. To do that, I use a payroll end date which is a weekly date. So in essence I have 4 dates where employee counts are shown. Some months have 5 dates which makes the row count for that month 5 instead of 4.
I then need to build an SSRS report to show only the first employee count and the last employee count per division, per month. I have the first number since I am using =IIF(Fields!RowNumber.Value = 1, Fields!EMPCOUNT.Value, 0)
The problem I have now is getting the last employee count where I need to conditionally select a count where row number needs to be 5 if exists or 4 if it doesn't exist. I'm not sure how to get the expression to work in SSRS. Sample data is below.
PRCo EMPCOUNT udDivision PREndDate ROWNUM Type
1 89 Civil 2018-01-06 00:00:00 1 1
1 97 Civil 2018-01-13 00:00:00 2 1
1 97 Civil 2018-01-20 00:00:00 3 1
1 97 Civil 2018-01-27 00:00:00 4 1
1 16 Colorado 2018-01-06 00:00:00 1 1
1 18 Colorado 2018-01-13 00:00:00 2 1
1 14 Colorado 2018-01-20 00:00:00 3 1
1 10 Colorado 2018-01-27 00:00:00 4 1
1 94 Civil 2018-02-03 00:00:00 1 2
1 91 Civil 2018-02-10 00:00:00 2 2
1 92 Civil 2018-02-17 00:00:00 3 2
1 91 Civil 2018-02-24 00:00:00 4 2
1 16 Colorado 2018-02-03 00:00:00 1 2
1 16 Colorado 2018-02-10 00:00:00 2 2
1 18 Colorado 2018-02-17 00:00:00 3 2
1 19 Colorado 2018-02-24 00:00:00 4 2
1 92 Civil 2018-03-03 00:00:00 1 3
1 91 Civil 2018-03-10 00:00:00 2 3
1 88 Civil 2018-03-17 00:00:00 3 3
1 92 Civil 2018-03-24 00:00:00 4 3
1 90 Civil 2018-03-31 00:00:00 5 3
1 19 Colorado 2018-03-03 00:00:00 1 3
1 26 Colorado 2018-03-10 00:00:00 2 3
1 25 Colorado 2018-03-17 00:00:00 3 3
1 27 Colorado 2018-03-24 00:00:00 4 3
1 24 Colorado 2018-03-31 00:00:00 5 3
I would do this in your query rather than trying to get it to work directly in SSRS. There might be a simpler way than this but this is just based on your existing query.
Please note this is untested and just off the top of my head so it may need some editing before it will work.
SELECT * INTO #t FROM YOUR_EXISTING_QUERY
SELECT DISTINCT
PRCo
, udDivision
, YEAR(PREndDate) AS Yr
, MONTH(PREndDate) AS Mnth
, FIRST_VALUE(EMPCOUNT) OVER(PARTITION BY PRCo, udDivision, YEAR(PREndDate), MONTH(PREndDate) ORDER BY ROWNUM) AS OpeningEMPCOUNT
, LAST_VALUE(EMPCOUNT) OVER(PARTITION BY PRCo, udDivision, YEAR(PREndDate), MONTH(PREndDate) ORDER BY ROWNUM) AS CLosing_EMPCOUNT
FROM #t
Yo might need to include Type not sure what this does but you get the idea hopefully.
The FIRST_VALUE and LAST_VALUE functions simply get the first/last value within the partition defined, in your case PRCo, udDivision and then just the year and month portion of the payroll end date, the first and last positions are determined by the order clause, in this case row number.

MS SQL: Group by date [duplicate]

This question already has answers here:
Sql Date Grouping with avaliable dates in database
(3 answers)
Closed 4 years ago.
ID DateTime EmailCount
93 6/1/2014 00:00:00 4
94 6/2/2014 00:00:00 4
95 6/3/2014 00:00:00 2
96 6/4/2014 00:00:00 2
97 6/5/2014 00:00:00 2
98 6/6/2014 00:00:00 2
99 6/7/2014 00:00:00 2
73 6/8/2014 00:00:00 2
74 6/9/2014 00:00:00 2
75 6/10/2014 00:00:00 4
76 6/11/2014 00:00:00 4
77 6/12/2014 00:00:00 2
78 6/13/2014 00:00:00 2
79 6/14/2014 00:00:00 2
80 6/16/2014 00:00:00 2
81 6/17/2014 00:00:00 4
82 6/18/2014 00:00:00 4
83 6/19/2014 00:00:00 4
84 6/20/2014 00:00:00 4
100 6/21/2014 00:00:00 4
101 6/22/2014 00:00:00 4
102 6/23/2014 00:00:00 4
103 6/24/2014 00:00:00 4
89 6/27/2014 00:00:00 4
90 6/28/2014 00:00:00 4
91 6/29/2014 00:00:00 4
92 6/30/2014 00:00:00 4
104 7/1/2014 00:00:00 4
105 7/2/2014 00:00:00 4
106 7/3/2014 00:00:00 4
121 7/6/2014 00:00:00 2
122 7/7/2014 00:00:00 2
123 7/8/2014 00:00:00 2
Generated Output
Startdate EndDate EmailCount
6/3/2014 00:00:00 6/14/2014 00:00:00 2
6/16/2014 00:00:00 6/16/2014 00:00:00 2
7/6/2014 00:00:00 7/8/2014 00:00:00 2
6/1/2014 00:00:00 6/11/2014 00:00:00 4
6/17/2014 00:00:00 6/24/2014 00:00:00 4
6/27/2014 00:00:00 7/3/2014 00:00:00 4
Here, the generated output is not perfect because I want StartDate to EndDate in groups like: (6/3/2014 to 6/9/2014 and EmailCount = 2) and (6/10/2014 to 6/11/2014 and EmailCount =4) and (6/12/2014 to 6/14/2014 and EmailCount =2). Also, date not in database should not be added to group.
A somewhat complex query to explain, but here goes an attempt;
If the time is always midnight, you could use a common table expression to assign a row number to each row, and group by the difference between the date and row number. As long as the sequence is not broken (ie the dates are consecutive and with the same emailid) they will end up in the same group and an outer query can easily extract the start and end date for each group;
WITH cte AS (
SELECT dateandtime, emailid,
ROW_NUMBER() OVER (PARTITION BY emailid ORDER BY dateandtime) rn
FROM mytable
)
SELECT MIN(dateandtime) start_time,
MAX(dateandtime) end_time,
MAX(emailid) emailid
FROM cte GROUP BY DATEADD(d, -rn, dateandtime) ORDER BY start_time
An SQLfiddle to test with.
If the datetimes are not always midnight, the grouping will fail. If that's the case, you could add a common table expression that converts the datetime to a date as a separate step before running this query.
You're looking for runs of consecutive dates in blocks with the same EmailID. This assumes you have no gaps in the dates. I'm not sure it's the most elegant approach but you can find a lot of stuff on this topic.
with BlockStart as (
select t.StartDate, t.EmailID
from T as t left outer join T as t2
on t2.StartDate = t1.StartDate - 1 and t2.EmailID = t1.EmailID
where t2.StartDate is null
union all
select max(StartDate) + 1, null
from T
) as BlockStart
select
StartDate,
(select min(StartDate) - 1 from BlockStart as bs2 where bs2 > bs.StartDate) as EndDate,
EmailID
from BlockStart as bs
where
EmailID is not null
-- /* or */ exists (select 1 from BlockStart as bs3 where bs3.StartDate > bs.StartDate)

Resources