Is Follow-up record created within 7 days? - sql

I have the following sample data, and what I'm trying to determine is show the ClientIDs where a Schedule record has a DateCompleted value, but has not had a Complete Type record created within 7 days.
Based off the below data, ClientID 1 only would be returned.
Create Table #temp
(
ClientID int,
Type varchar(50),
DateCreated datetime,
DateCompleted datetime
)
insert into #temp
(
ClientID,
Type,
DateCreated,
DateCompleted
)
select
1,
'Schedule',
'01 Oct 2020',
'20 Oct 2020'
union all
select
2,
'Schedule',
'15 Oct 2020',
'01 Nov 2020'
union all
select
4,
'Schedule',
'15 Oct 2020',
'01 Nov 2020'
union all
select
4,
'Complete',
'02 Nov 2020',
'02 Nov 2020'
union all
select
5,
'Schedule',
'15 Sep 2020',
'25 Sep 2020'
union all
select
5,
'Complete',
'02 Oct 2020',
'02 Oct 2020'
union all
select
5,
'Schedule',
'15 Oct 2020',
NULL

If I understand correctly, ids 1 and 1 should both be returned.
The following returns all clients with a valid schedule complete time, but no "completed" record within 7 days:
select distinct t.clientId
from temp t
where t.type = 'Schedule' and
t.datecompleted is not null and
not exists (select 1
from temp t2
where t2.clientid = t.clientid and
t2.type = 'Complete' and
datediff(day, t.datecompleted, t2.datecompleted) <= 7
);
Here is a db<>fiddle.
EDIT:
Based on your comment, you need a comparison to the current date:
select distinct t.clientId
from temp t
where t.type = 'Schedule' and
t.datecompleted < dateadd(day, -7, getdate()) and
not exists (select 1
from temp t2
where t2.clientid = t.clientid and
t2.type = 'Complete' and
datediff(day, t.datecompleted, t2.datecompleted) <= 7
);

As far as I can understand that you can use DATEDIFF() function with day as the first argument
SELECT *,
CASE WHEN DATEDIFF(day, DateCreated, DateCompleted ) <= 7 THEN
'Yes'
ELSE
'No'
END AS "Completed IN One Week"
FROM #temp
Update : depending on the comment; need to see whether there is an associated "Complete" row use this query :
SELECT ClientID
FROM #temp
GROUP BY ClientID
HAVING SUM(CASE WHEN Type='Complete' THEN 1 END)>0
Demo

Phillip, I hope this will help you.
Select * from #temp where datecompleted is not null and type='Schedule' and datediff(d,datecompleted,getdate())>7 and clientid not in (select distinct Clientid from #temp where type='Complete')

Related

Is there a SQL INSERT Statement to Insert Records from Previous Month if Not exists for Current Month?

TableA:
ID Amount Date
-------------------------
1 100 02/02/2020
2 100 02/02/2020
1 100 03/10/2020 Insert Feb record with March date
2 100 03/10/2020 Insert Feb record with March date
3 100 03/10/2020
4 100 03/10/2020
1 100 04/03/2020
4 100 04/03/2020
2 100 04/03/2020 Insert MAR record with APR date
3 100 04/03/2020 Insert MAR record with APR date
The Processing Date is always different.
I tried using NOT EXISTS but it selects all old rows, but I only need previous date rows only
DECLARE #ProcessingDate DateTime
SET #ProcessingDate = '04/03/2020'
SELECT DISTINCT
t1.ID, Amount, ProcessingDate
FROM
TABLE1 t1
WHERE
NOT EXISTS (SELET *
FROM TABLE1 t2
WHERE t2.ID = t1.ID
AND t2.ProcessingDate = #ExpenseProcessingDate)
I tried using the LAG function but it's also selecting all records
DECLARE #ProcessingDate DateTime
SET #ProcessingDate = '04/03/2020'
SELECT
*,
LAG(#ProcessingDate) OVER (Partition BY ID, Amount ORDER BY ProcessingDate) AS PrevEvent
FROM
Table1 A
WHERE
NOT EXISTS (SELECT * FROM TABLE1 A1
WHERE A1.ID = A.ID
AND A1.ProcessingDate = #ProcessingDate)
I don't fully understand what you are asking... but to further filter your query down to only the previous month, use the following:
declare #ProcessingDate datetime = '04/03/2020', #StartDate datetime, #EndDate datetime;
select #StartDate = getdate();
select #StartDate = convert(datetime, '01/' + convert(varchar(2), datepart(month, dateadd(month, -1, #StartDate))) + '/' + datename(year, dateadd(month, -1, #StartDate)), 103);
select #EndDate = dateadd(day, -1, dateadd(month, 1, #StartDate));
-- select #StartDate StartDate, #EndDate EndDate
SELECT t1.ID,Amount, ProcessingDate
FROM dbo.Table2 t2
WHERE NOT EXISTS (
SELECT 1
FROM dbo.Table1 t1
WHERE t1.ID = t2.ID
AND t1.ProcessingDate = #ExpenseProcessingDate
)
-- Only include records from the previous month
AND t2.ProcessingDate >= #StartDate AND t2.ProcessingDate < dateadd(day, 1, #EndDate);
Note I changed the aliases to match the table names for clarity.
I keep a bunch of standard code snippets lying around for reports e.g. last month, last quarter, last week etc.

SQL Person by month Data

I have a data set with
Name|ID|Start_DATE|END_DATE
I would like to get a break out of active months.
Example:
Bob Smith|1001|2016-12-01|2017-02-18
would return all the months listed between the dates
Bob Smith|1001|2016-12-01
Bob Smith|1001|2017-01-01
Bob Smith|1001|2017-02-02
I have been planing with some data based on dates I found. I will also need to deal with the active employees listed as 9999-12-31 once I figure out the base query.
declare #startDate date;
declare #endDate date;
select #startDate = '20100101';
select #endDate = '20150531';
with dateRange as
(
select dt = dateadd(mm, 0, #startDate)
where dateadd(mm, 0, #startDate) < #endDate
union all
select dateadd(mm, 1, dt)
from dateRange
where dateadd(mm, 1, dt) < #endDate
)
select *
from dateRange
Is there a better way to handle it?
Assuming I understand the question, here is one way to do it:
First, Create and populate sample table (Please save us this step in your future questions)
DECLARE #T AS TABLE
(
Name varchar(20),
ID int,
Start_DATE date,
END_DATE date
)
INSERT INTO #T VALUES
('Bob Smith', 1001, '2016-12-01', '2017-02-18')
The DateRange calendar cte from your question, with dates that fits the sample data:
declare #startDate date;
declare #endDate date;
select #startDate = '20150101';
select #endDate = '20200531';
with dateRange as
(
select dt = dateadd(mm, 0, #startDate)
where dateadd(mm, 0, #startDate) < #endDate
union all
select dateadd(mm, 1, dt)
from dateRange
where dateadd(mm, 1, dt) < #endDate
)
The query:
SELECT Name,
ID,
CONVERT(char(12), Start_DATE, 107) As StartDate, -- just to see it clearly in the results
CONVERT(char(12), END_DATE, 107) As EndDate, -- just to see it clearly in the results
CONVERT(char(12), dt, 107) As ActiveMonth
FROM #T
INNER JOIN dateRange ON dt >= Start_DATE AND dt < END_DATE
Results:
Name ID StartDate EndDate ActiveMonth
Bob Smith 1001 Dec 01, 2016 Feb 18, 2017 Dec 01, 2016
Bob Smith 1001 Dec 01, 2016 Feb 18, 2017 Jan 01, 2017
Bob Smith 1001 Dec 01, 2016 Feb 18, 2017 Feb 01, 2017
BTW, there is a better way to create a calendar cte, using a numbers (or tally) table. here a demo.

Grouping Fiscal year using SQL Server

Is there a way in SQL Server that can show the Fiscal Year (begins on October 1 and ends on September 30) from a table which has a date column (1998 to 2010). Here is what I have done:
select 'FY1999' as FY, site, count(*)
from mytable
where mydate >='10/1/1998'
and mydate <'10/1/1999'
group by site
select 'FY2000' as FY, site, count(*)
from mytable
where mydate >='10/1/1999'
and mydate <'10/1/2000'
group by site
select 'FY2001' as FY, site, count(*)
from mytable
where mydate >='10/1/2000'
and mydate <'10/1/2001'
group by site
Isn't it too much repetitive when doing this for more then 10 FY year?
Here's a single query that will give you the information you want.
SELECT DATEPART(yyyy, DATEADD(mm, 3, mydate)) AS FY, site, COUNT(*) AS row_count
FROM mytable
GROUP BY DATEPART(yyyy, DATEADD(mm, 3, mydate)), site
You can even create your user-defined function in SQL Server that takes a date argument and returns the fiscal year as an int:
CREATE FUNCTION GetFiscalYear(#TheDate date)
RETURNS int
AS
BEGIN
DECLARE #FiscalYear int
IF DATEPART(month, #TheDate) < 10
SELECT #FiscalYear = DATEPART(year, #TheDate)
ELSE
SELECT #FiscalYear = DATEPART(year, #TheDate) + 1
RETURN #FiscalYear
END
Then you can use this as, for example:
SELECT Id, ShippingDate, GetFiscalYear(ShippingDate)
FROM SomeTable
Yes, it is a bit repetitive. I'd be using DatePart and some easy to discern rules:
Fiscal year is the year of the date if the month is < 10.
Fiscal year is the year of the date + 1 if the month >= 10
This is the dynamic script for UK, April to March,
for different dates you can use as refernece,
Good Luck
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SET #StartDate = DATEADD(dd,0, DATEDIFF(dd,0, DATEADD( mm, -(((12 + DATEPART(m, getDate())) - 4)%12), getDate() ) - datePart(d,DATEADD( mm, -(((12 + DATEPART(m, getDate())) - 4)%12),getDate() ))+1 ) )
SET #EndDate = DATEADD(SS,-1,DATEADD(mm,12,#StartDate))
SELECT #StartDate,#EndDate
Start of fiscal year:
DATEADD(MONTH, DATEDIFF(MONTH, '20100401', getdate()) / 12 * 12, '20100401')
End of Fiscal Year
DATEADD(MONTH, DATEDIFF(MONTH, '20100401', getdate()) / 12 * 12, '20110331')
Replace getdate() with your own date if required
I don't have a SQL server reference handy, but here's how I'd do it in MySQL:
select date_format (date_add(mydate, interval 92 days), 'FY%Y') as FY, site, count(*)
from mytable
group by FY, site;
There are 92 days in October, November, and December, so I've offset by that much.
Yesterday there was an answer to this question, which was subsequently deleted.
I do not know why. Was there something wrong with it?
Please don't vote this answer down, I just want to know why it was deleted.
With vigorous testing, I still can't manage to fault it. In my example, Fiscal year starts July 1.
The answer was:
SELECT SUM(value), CAST(Year(DateAdd(Month, -6, TransactionDate)) as varchar) + ' - ' + CAST(Year(DateAdd(Month, 6, TransactionDate)) as varchar) as 'FY'
FROM mytable
GROUP BY CAST(Year(DateAdd(Month, -6, mydate)) as varchar) + ' - ' + CAST(Year(DateAdd(Month, 6, mydate)) as varchar)
Here is some test Sql based on Simon's answer
DECLARE #basestartdate datetime, #baseenddate datetime
SET #basestartdate = CAST('1 April 1753' AS datetime)
SET #baseenddate = CAST('31 March 1754' AS datetime)
;
WITh TestData as
(
SELECT
CAST('1 April 2015' AS datetime) input,
CAST('1 April 2015' AS datetime) expectedstartdate,
CAST('31 March 2016' AS datetime) expectedenddate UNION SELECT
CAST('2 April 2015' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('31 December 2015' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('1 January 2016' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('28 February 2016' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('31 March 2016' AS datetime),
CAST('1 April 2015' AS datetime),
CAST('31 March 2016' AS datetime) UNION SELECT
CAST('1 April 2016' AS datetime),
CAST('1 April 2016' AS datetime),
CAST('31 March 2017' AS datetime)
),
Results AS
(
SELECT
input,
expectedstartdate,
DATEADD(MONTH,
12 * (DATEDIFF(MONTH, #basestartdate, input) / 12),
#basestartdate) startdate,
expectedenddate,
DATEADD(MONTH,
12 * (DATEDIFF(MONTH, #basestartdate, input) / 12),
#baseenddate) enddate
FROM testdata
)
SELECT
CASE
WHEN (expectedstartdate = startdate) THEN 'Pass' ELSE 'Fail'
END startdateresult,
CASE
WHEN (expectedenddate = enddate) THEN 'Pass' ELSE 'Fail'
END startdateresult
FROM results
ORDER BY input

Datetime selection query group by day

I've got a question for my SQL query I've got too write. It's a long time ago since I've written an query so I could use some help with mine. I've tried looking for examples but didn't find the right result. Ive written an query but its really isn't working for me..
What im trying to do is get the sum of the total power consumption for each date in my database.
My table looks like:
|HistoryProbes|
|-------------|
|id (int) pk |
|timestamp (datetime) formatted as: "yyyy-MM-ddTHH:mm:ss"|
|PowerConsumption (int)|
I've found a sample that did quite work.. But it isnt the best solution for me..
it can be found at : http://cephas.net/blog/2005/12/06/sql-server-group-by-datetime/
So far i got this working
SELECT distinct CONVERT(varchar, timestamp, 111) AS thedate
FROM HistoryProbes
I got values 25/11/2009 and 24/11/2009 but i cant manage to get the sum of the PowerConsumption
Thanks.
Something like this will give you the sum per day
DECLARE #HistoryProbes TABLE(
id INT,
timesmp DATETIME,
PowerConsumption INT
)
INSERT INTO #HistoryProbes (id,timesmp,PowerConsumption) SELECT 1, '01 Jan 2009 12:00:00',1
INSERT INTO #HistoryProbes (id,timesmp,PowerConsumption) SELECT 2, '01 Jan 2009 11:00:00',2
INSERT INTO #HistoryProbes (id,timesmp,PowerConsumption) SELECT 3, '01 Jan 2009 13:00:00',3
INSERT INTO #HistoryProbes (id,timesmp,PowerConsumption) SELECT 4, '01 Jan 2009 14:00:00',4
INSERT INTO #HistoryProbes (id,timesmp,PowerConsumption) SELECT 5, '02 Jan 2009 12:00:00',14
INSERT INTO #HistoryProbes (id,timesmp,PowerConsumption) SELECT 6, '02 Jan 2009 11:00:00',24
INSERT INTO #HistoryProbes (id,timesmp,PowerConsumption) SELECT 7, '03 Jan 2009 13:00:00',34
INSERT INTO #HistoryProbes (id,timesmp,PowerConsumption) SELECT 8, '03 Jan 2009 14:00:00',44
SELECT DATEADD(dd,0, DATEDIFF(dd,0,timesmp)),
SUM(PowerConsumption)
FROM #HistoryProbes
GROUP BY DATEADD(dd,0, DATEDIFF(dd,0,timesmp))
select CONVERT(varchar, timestamp, 111) as timestamp_by_day
, sum(PowerConsumption) as total_power
from HistoryProbes
group by CONVERT(varchar, timestamp, 111)
order by CONVERT(varchar, timestamp, 111)
Try this:
SELECT Convert(varchar, timestamp, 111) as thedate, SUM(PowerConsumption) as Total
FROM HistoryProbes
GROUP BY Convert(varchar, timestamp, 111)
I'm not sure why you need distinct in there; since you're not joining to any other tables

SQL To find difference between multiple rows

I have a table containing multiple records for different transactions i.e.
ID Date REF
1 01/09/2008 A
1 11/09/2008 A
1 01/10/2008 A
2 01/09/2008 A
2 01/10/2008 A
2 01/11/2008 B
2 01/12/2008 B
and I'm looking to summarise the data so that I have the average days for each id and ref...
i.e.
ID Ref Avg_Days
1 A 15
2 A 30
2 B 30
Thanks in advance if anyone can help
Average day difference is a SUM of differences divided by COUNT(*)
SUM of differences is in fact difference between MIN and MAX:
SELECT id, ref, DATEDIFF(day, MIN(date), MAX(date)) / NULLIF(COUNT(*) - 1, 0)
FROM mytable
GROUP BY
id, ref
Something like this... not really sure how this info will help you with anything though.... need more info as to what your trying to average the days for.
SELECT ID, REF, AVG(DATEPART(day, [Date]))
FROM dbo.Table1
GROUP BY ID, REF
Reference:
AVG,
DATEPART
Using sql server 2005 try this.
DECLARE #Table TABLE(
ID INT,
Date DATETIME,
Ref VARCHAR(MAX)
)
INSERT INTO #Table (ID,Date,Ref) SELECT 1, '01 Sep 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 1, '11 Sep 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 1, '01 Oct 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 2, '01 Sep 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 2, '01 Oct 2008', 'A'
INSERT INTO #Table (ID,Date,Ref) SELECT 2, '01 Nov 2008', 'B'
INSERT INTO #Table (ID,Date,Ref) SELECT 2, '01 Dec 2008', 'B'
;WITH Ordered AS (
SELECT ID,
Ref,
Date,
ROW_NUMBER() OVER (PARTITION BY ID, Ref ORDER BY Date) SubNumber
FROM #Table t
)
SELECT Ordered.ID,
Ordered.Ref,
AVG(DATEDIFF(dd, Ordered.Date, OrderedNext.Date)) AVG_Days
FROM Ordered INNER JOIN
Ordered OrderedNext ON Ordered.ID = OrderedNext.ID
AND Ordered.Ref = OrderedNext.Ref
AND Ordered.SubNumber + 1 = OrderedNext.SubNumber
GROUP BY Ordered.ID,
Ordered.Ref
Also have a look at it mathematically:
Let say
([X(1)-X(0)] + [X(2)-X(1)] + [X(3)-X(2)] + ... + [X(n-1)-X(n-2)] + [X(n)-X(n-1)]) / (n-1).
expand the top part as
-X(0) + X(1) - X(1) + X(2) - X(2) + X(3) - ... - X(n-2) + X(n-1) - X(n-1) + X(n)
whcih end up as -X(0) + X(n)
so we have [X(n) - X(0)] / (n - 1)
so take (MAX - MIN) / (Count - 1) for count > 1