Incrementing while inserting sql - sql-server

I have a table as below:
Department Date Budget
-----------------------------------
D1 2010-01-01 100
D2 2010-01-01 200
... ... ...
Is there a way to write an insert statement that autoincrements the month and budget for a particular department?
For instance, I want to insert data for 2010 from Jan to Dec for department D1 with increments of 10 each month. So the resultant table should look something like below
Department Date Budget
------------------------------------
D1 2010-01-01 100
D2 2010-01-01 200
D1 2010-02-01 110
D1 2010-03-01 120
D1 2010-04-01 130
... ... ...
I know this can be achieved through some scripting, but is there a way to achieve this through just insert and select statements ?
Using SQL Server (or) Postgres

For Postgres:
insert into the_table (department, "date", budget)
select d.department,
d.date + interval '1 month' * row_number() over (order by g.i),
d.budget + row_number() over (order by g.i) * 10
from the_table d, generate_series(1,11) as g(i)
where d.department = 'D1';
This assumes that at the time when this is run, only a single row exists for department D1

try something like
insert into Table values
('D1',Dateadd(month,1,
(select top 1 Date from Table order by Date Desc)),budget)

using recursive cte
;With cte(Department,[Date], Budget)
AS
(
SELECT 'D1','2010-01-01', 100 UNION ALL
SELECT 'D2','2010-01-01', 200
)
,cte2 AS
(
SELECT 0 AS val ,
0 AS val2
UNION ALL
SELECT val +1,
val2+10
FROM cte2
WHERE val<11 )
INSERT INTO the_table (department, [date], budget)
SELECT department,
[date],
CASE
WHEN rnk=0 THEN budget
ELSE budget+val2
END AS Budget
FROM (
SELECT department,
val2,
Dateadd(month,val,[date])AS [Date],
budget,
Row_number()OVER(PArtition by Department ORDER BY [Date])-1 AS Rnk
FROM Cte2 ,
Cte )dt
WHERE dt.department='D1'
Result
department Date Budget
-------------------------------------------
D1 2010-01-01 00:00:00.000 100
D1 2010-02-01 00:00:00.000 110
D1 2010-03-01 00:00:00.000 120
D1 2010-04-01 00:00:00.000 130
D1 2010-05-01 00:00:00.000 140
D1 2010-06-01 00:00:00.000 150
D1 2010-07-01 00:00:00.000 160
D1 2010-08-01 00:00:00.000 170
D1 2010-09-01 00:00:00.000 180
D1 2010-10-01 00:00:00.000 190
D1 2010-11-01 00:00:00.000 200
D1 2010-12-01 00:00:00.000 210

Related

Get the SUM of a DATEDIFF result

I have a SQL statement (MS SQL Server 2012) that makes a simple calculation of the differences in dates in some records. I want to return the total / sum of the DATEDIFFs as well.
This is my query:
with cte as (
select ROW_NUMBER () OVER (ORDER BY Date) as ID, Die_ID, Date, Status
from Tooling_Status
where (date between '2018-02-27 00:00:00' and '2019-02-27 11:59:59')
and Date is not null)
select DATEDIFF (ss, c1.Date, min (c2.Date)) as Seconds, convert (nvarchar (10), c1.Date, 120) as DIA
from cte c1
left outer join cte c2
on c1.Date < c2.Date and c1.Die_ID = c2.Die_ID
where c1.Status = 2 and c2.Status = 1
group by c1.Date
order by DIA desc
And this my result:
Seconds DAY
2253 2019-02-27
166 2019-02-27
17 2019-02-27
104 2019-02-27
36 2019-02-27
11 2019-02-07
20 2019-02-07
32 2019-02-07
22 2019-02-07
27 2019-02-07
33 2019-02-07
15 2019-02-07
34 2019-02-07
120 2019-02-04
99420 2019-01-07
60 2018-09-26
I need this result:
Seconds DAY
2732 2019-02-27
194 2019-02-07
120 2019-02-04
99420 2019-01-07
60 2018-09-26
Thanks For Help!
Few adjustments
Extra GROUP BY using a derived table
Removed unnecessary casts to a string
Formatting...
SQL:
WITH cte
AS (SELECT ROW_NUMBER() OVER (ORDER BY Date) AS ID,
Die_ID,
Date,
Status
FROM Tooling_Status
WHERE (date BETWEEN '2018-02-27 00:00:00' AND '2019-02-27 11:59:59' )
AND Date IS NOT NULL
)
SELECT SUM(d.Seconds) AS Seconds
, d.DIA AS [Day]
FROM (
SELECT DATEDIFF(ss, c1.Date, MIN(c2.Date)) AS Seconds,
CAST(c1.Date AS DATE) AS DIA
FROM cte c1
LEFT OUTER JOIN cte c2
ON c1.Date < c2.Date
AND c1.Die_ID = c2.Die_ID
WHERE c1.Status = 2 AND c2.Status = 1
GROUP BY c1.Date
) d
GROUP BY d.DIA
ORDER BY [Day] DESC;

Get the count of days across multiple rows

This is for SQL Server 2008/2012.
I have the following dataset with the claim start date and end date. I want to calculate the number of days when there are back to back claims where the claim start date of the next date is one day after the claim end date of the previous date, making it a continuous service.
If there is a break in service, like for member id 1002 where the claim end of 05/15 and next one starts on 05/18, the count should restart.
MemberID Claim Start Claim End Claim_ID
1001 2016-04-01 2016-04-15 ABC11111
1001 2016-04-16 2016-04-30 ABC65465
1001 2016-05-01 2016-05-15 ABC51651
1001 2016-05-16 2016-06-15 ABC76320
1002 2016-04-01 2016-04-15 ABC74563
1002 2016-04-16 2016-04-30 ABC02123
1002 2016-05-01 2016-05-15 ABC02223
1002 2016-05-18 2016-06-15 ABC66632
1002 2016-06-16 2016-06-30 ABC77447
1002 2016-07-10 2016-07-31 ABC33221
1002 2016-08-01 2016-08-10 ABC88877
So effectively, I want the following output. Min of the very first claim start date, max of the claim end date when there is no gap in coverage between multiple claims. If there is a gap in coverage, the count starts over and the min of the start date of the 1st claim and the max of the claim end date until there is no gap in coverage between multiple claims.
MemberID Claim_Start Claim_End Continuous_Service_Days
1001 2016-04-01 2016-06-15 76
1002 2016-04-01 2016-05-15 45
1002 2016-05-18 2016-06-30 44
1002 2016-07-10 2016-08-10 32
I have tried while loops, CTE's and I have also tried the following table to first get all the dates between the claims. But I am having problems with counting the days between consecutive dates and to reset the count if there is a break in coverage.
Master.dbo.spt_values
Any help is appreciated. Thanks!
You need to find the gaps first.
This solution uses a Tally Table to generate the dates first from ClaimStart to ClaimEnd. Then using the generated dates, get the gaps using this method.
Now that you have the gaps, you can now use GROUP BY to ge the MIN(ClaimStart) and MAX(ClaimStart):
WITH E1(N) AS( -- 10 ^ 1 = 10 rows
SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), -- 10 ^ 2 = 100 rows
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), -- 10 ^ 4 = 10,000 rows
CteTally(N) AS(
SELECT TOP(SELECT MAX(DATEDIFF(DAY, ClaimStart, ClaimEnd) + 1) FROM tbl)
ROW_NUMBER() OVER(ORDER BY(SELECT NULL))
FROM E4
),
CteDates AS( -- Generate the dates from ClaimStart to ClaimEnd
SELECT
t.MemberID,
dt = DATEADD(DAY, ct.N - 1, t.ClaimStart)
FROM tbl t
INNER JOIN CteTally ct
ON DATEADD(DAY, ct.N - 1, t.ClaimStart) <= t.ClaimEnd
),
CteGrp AS( -- Find gaps and continuous dates
SELECT *,
rn = DATEADD(DAY, - ROW_NUMBER() OVER(PARTITION BY MemberID ORDER BY dt), dt)
FROM CteDates
)
SELECT
MemberID,
ClaimStart = MIN(dt),
ClaimEnd = MAX(dt),
Diff = DATEDIFF(DAY, MIN(dt), MAX(dt)) + 1
FROM CteGrp
GROUP BY MemberID, rn
ORDER BY MemberID, ClaimStart;
ONLINE DEMO
Declare #YourTable table (MemberID int,[Claim Start] date,[Claim End] date,[Claim_ID] varchar(25))
Insert Into #YourTable values
(1001,'2016-04-01','2016-04-15','ABC11111'),
(1001,'2016-04-16','2016-04-30','ABC65465'),
(1001,'2016-05-01','2016-05-15','ABC51651'),
(1001,'2016-05-16','2016-06-15','ABC76320'),
(1002,'2016-04-01','2016-04-15','ABC74563'),
(1002,'2016-04-16','2016-04-30','ABC02123'),
(1002,'2016-05-01','2016-05-15','ABC02223'),
(1002,'2016-05-18','2016-06-15','ABC66632'),
(1002,'2016-06-16','2016-06-30','ABC77447'),
(1002,'2016-07-10','2016-07-31','ABC33221'),
(1002,'2016-08-01','2016-08-10','ABC88877')
;with cte0(N) as (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N))
,cte1(R,D) as (Select Row_Number() over (Order By (Select Null))
,DateAdd(DD,-1+Row_Number() over (Order By (Select Null)),(Select MinDate=min([Claim Start]) From #YourTable))
From cte0 N1, cte0 N2, cte0 N3, cte0 N4)
Select MemberID
,[Claim Start] = Min([Claim Start])
,[Claim End] = Max([Claim End])
,Continuous_Service_Days = count(*)
From (
Select *,Island = R - Row_Number() over (Partition By MemberID Order by [Claim Start])
From #YourTable A
Join cte1 B on D Between [Claim Start] and [Claim End]
) A
Group By MemberID,Island
Order By 1,2
Returns
MemberID Claim Start Claim End Continuous_Service_Days
1001 2016-04-01 2016-06-15 76
1002 2016-04-01 2016-05-15 45
1002 2016-05-18 2016-06-30 44
1002 2016-07-10 2016-08-10 32

SQL Server TSQL: Put Subsequent (date) rows into bins

i have following table:
id insertDate
1 2015-01-01
22 2015-01-02
43 2015-01-03
46 2015-01-06
124 2015-01-07
In the end i want to have a possiblity to group the rows that differ exaclty in one day so in that case
id insertDate groups
1 2015-01-01 1
22 2015-01-02 1
43 2015-01-03 1
46 2015-01-06 2
124 2015-01-07 2
How is this possible? I bet it is some fancy window function usage
This is a "gaps and islands" problem.
One approach is below. This works on SQL Server 2005+. I have assumed that insertDate is unique as per your example data.
WITH CTE
AS (SELECT *,
DATEDIFF(DAY, 0, [insertDate]) - ROW_NUMBER() OVER (ORDER BY ID) AS Grp
FROM YourTable)
SELECT [id],
[insertDate],
DENSE_RANK() OVER (ORDER BY Grp) AS Grp
FROM CTE

Calculating Time difference from multiple value without having any flag in SQL Server

I need to calculate break time taken by employee, sample shown here:
Userid Date_time
------ ---------
1001 9/1/15 10:31 AM
1001 9/1/15 11:51 AM
1001 9/1/15 11:58 AM
1001 9/1/15 2:02 PM
1001 9/1/15 2:38 PM
1001 9/1/15 4:37 PM
1001 9/1/15 5:12 PM
1001 9/1/15 6:32 PM
1001 9/1/15 6:34 PM
1001 9/1/15 7:39 PM
1001 9/1/15 7:42 PM
1001 9/1/15 7:53 PM
Hence I don't want first and last record because it will be calculated as total working hours.
Expected result:
Userid break_time_MIN
------ --------------
1001 83
Please suggest how I can calculate the break time for each employee.
First, you want to remove the first and last row. After that, you want to group two consecutive rows and then get their difference. Finally, compute for the SUM of all the differences:
WITH Cte AS(
SELECT *,
grp = rn - (rn % 2 + 1)
FROM (
SELECT *,
rn = ROW_NUMBER() OVER(PARTITION BY Userid ORDER BY Date_time),
rnd = ROW_NUMBER() OVER(PARTITION BY Userid ORDER BY Date_time DESC)
FROM #tbl
) t
WHERE rn <> 1 AND rnd <> 1
),
CteFinal AS(
SELECT
Userid,
BreakDuration = DATEDIFF(MINUTE, MIN(Date_time), MAX(Date_time))
FROM Cte
GROUP BY
Userid, grp
)
SELECT
Userid,
break_time_MIN = SUM(BreakDuration)
FROM CteFinal
GROUP BY UserId;
ONLINE DEMO
---------------------
Result:
---------------------
Userid break_time_MIN
------ --------------
1001 83
;WITH cte AS (
SELECT Userid,
Date_time,
ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY UserId, Date_time) as RN
FROM YourTableName)
SELECT r1.Userid, SUM(DATEDIFF(MINUTE,r1.Date_time,r2.Date_time)) as break_time
FROM cte r1
INNER JOIN cte r2
ON r1.Userid = r2.Userid AND r1.RN + 1 = r2.RN
WHERE r1.RN % 2 = 0
GROUP BY r1.Userid
Output:
Userid break_time
1001 83

How to pick last inserted DateTime from each month?

I have a table PriceDate with two columns PriceId and PriceDate with 3-4 entries per month.
I want to retrieve last inserted PriceDate for each month.
This is my table
PriceDate PriceId
2012-01-07 00:00:00.000 1
2012-01-14 00:00:00.000 2
2012-01-21 00:00:00.000 3
2012-01-28 00:00:00.000 4
2012-02-04 00:00:00.000 5
2012-02-11 00:00:00.000 6
2012-02-18 00:00:00.000 7
2012-02-25 00:00:00.000 8
I need this output
PriceDate DateFormat PriceId
2012-01-28 00:00:00.000 Jan 2012 4
2012-02-25 00:00:00.000 Feb 2012 8
This seems to do the trick:
declare #t table (PriceDate datetime not null, PriceId int not null)
insert into #t(PriceDate,PriceId) values
('2012-01-07T00:00:00.000',1),
('2012-01-14T00:00:00.000',2),
('2012-01-21T00:00:00.000',3),
('2012-01-28T00:00:00.000',4),
('2012-02-04T00:00:00.000',5),
('2012-02-11T00:00:00.000',6),
('2012-02-18T00:00:00.000',7),
('2012-02-25T00:00:00.000',8)
;With Numbered as (
select *,
ROW_NUMBER() OVER (
PARTITION BY DATEADD(month,DATEDIFF(month,0,PriceDate),0)
ORDER BY PriceDate desc) as rn
from #t
)
select PriceDate,
RIGHT(CONVERT(varchar(20),PriceDate,106),8) [Dateformat],
PriceId
from Numbered where rn=1
The DATEADD/DATEDIFF trick is to basically round every date to the start of its respective month.
Result:
PriceDate Dateformat PriceId
----------------------- -------- -----------
2012-01-28 00:00:00.000 Jan 2012 4
2012-02-25 00:00:00.000 Feb 2012 8
Similar to #Damian_The_Unbeliever's but using the YEAR() and Month() functions
;WITH DateOrdered
AS
(
SELECT PriceDate, PriceId,
ROW_NUMBER() OVER (
PARTITION BY YEAR(PriceDate), MONTH(PriceDate)
ORDER BY PriceDate DESC) As Num
from PriceDate
)
SELECT PriceDate, RIGHT(CONVERT(varchar(20),PriceDate,106),8) [Dateformat], PriceId
FROM DateOrdered
WHERE Num = 1

Resources