SQL Select Data - sql-server

I have a table set up, it is a customers' repayment schedule for a product.
My table consists of the following fields:
SaleID | PaymentDueDate | AmountDue
What I need for each Sale is:
SaleID | FirstPaymentDate | FirstPaymentValue | RegularPaymentValue | FinalPaymentvalue
Each repayment schedule has the following characteristics:
First payment amount is defined by the customer.
Regular and final payments are dictated by the balance remaining.
e.g
Sale = £200
Term = 14 Weeks (14 Payments)
First Payment = £50 (x1)
Regular Payment = £12 (x12)
Final Payment = £6 (x1)
Please can you advise how I can retrieve what I need.
ADDITION:
Code So Far:
This is what I have achieved so far, but this only gets me the First Payment and First Payment Date for each Sale:
SELECT
FP.SaleID, FP.FirstPaymentDate, RS.AmountDue AS FirstPayment
FROM
(
SELECT SaleID, MIN(PaymentDueDate)AS FirstPaymentDate
FROM RepaymentSchedule
GROUP BY SaleID
) AS FP
LEFT OUTER JOIN
RepaymentSchedule AS RS ON FP.SaleID = RS.SaleID AND FP.FirstPaymentDate = RS.PaymentDueDate ORDER BY RS.SaleID
ADDITION:
Data Sample:
£280 over 14 Weeks
SaleID PaymentDueDate AmountDue
41 2012-08-29 00:00:00.000 120.00
41 2012-09-05 00:00:00.000 12.30
41 2012-09-12 00:00:00.000 12.30
41 2012-09-19 00:00:00.000 12.30
41 2012-09-26 00:00:00.000 12.30
41 2012-10-03 00:00:00.000 12.30
41 2012-10-10 00:00:00.000 12.30
41 2012-10-17 00:00:00.000 12.30
41 2012-10-24 00:00:00.000 12.30
41 2012-10-31 00:00:00.000 12.30
41 2012-11-07 00:00:00.000 12.30
41 2012-11-14 00:00:00.000 12.30
41 2012-11-21 00:00:00.000 12.30
41 2012-11-28 00:00:00.000 12.40
I guess the FinalPaymentValue is not too crucial.
Really I just need to know how to work out what the regular payment is.

This should work:
SELECT pd.saleid,
pd.firstpaymentdate AS FirstPaymentDate,
(SELECT amountdue
FROM repaymentschedule
WHERE saleid = pd.saleid
AND paymentduedate = pd.firstpaymentdate) AS FirstPaymentValue,
(SELECT TOP 1 amountdue
FROM repaymentschedule
WHERE saleid = pd.saleid
AND paymentduedate <> pd.firstpaymentdate
AND paymentduedate <> pd.lastpaymentdate) AS RegularPaymentValue,
(SELECT amountdue
FROM repaymentschedule
WHERE saleid = pd.saleid
AND paymentduedate = pd.lastpaymentdate) AS FinalPaymentValue
FROM (SELECT saleid,
Min(paymentduedate) AS FirstPaymentDate,
Max(paymentduedate) AS LastPaymentDate
FROM repaymentschedule
GROUP BY saleid) pd
See it in action
Sample Result:
| SALEID | FIRSTPAYMENTDATE | FIRSTPAYMENTVALUE | REGULARPAYMENTVALUE | FINALPAYMENTVALUE |
--------------------------------------------------------------------------------------------------------
| 41 | August, 29 2012 00:00:00+0000 | 120 | 12.3 | 12.4 |

Related

How to increment a column like 1, 1, 2, 2, 3, 3 in SQL Server

I have data like this in a table:
https://i.stack.imgur.com/JYZjz.png
I want to group first two events (1, 10) as F1, than second two events (1,10) as F2
Running this SQL query:
SELECT
Id, Date, Event,
CASE
WHEN Event = 1 AND LEAD(Event) OVER (ORDER BY ID) = 10
THEN 'F1'
WHEN Event = 10 AND LAG(Event) OVER (ORDER BY ID) = 1
THEN 'F1'
ELSE NULL
END AS Flow
FROM
lxfr.SystemEventsDiary
WHERE
Event IN (1, 10)
I get this result as output:
ID
Date
Event
Flow
4
2022-02-07 00:00:00.000
1
F1
44
2022-02-08 00:00:00.000
10
F1
47
2022-02-09 00:00:00.000
1
F1
72
2022-02-10 00:00:00.000
10
F1
75
2022-02-10 00:00:00.000
1
F1
97
2022-02-11 00:00:00.000
10
F1
100
2022-02-11 00:00:00.000
1
NULL
113
2022-02-28 00:00:00.000
1
F1
217
2022-03-04 00:00:00.000
10
F1
235
2022-03-22 00:00:00.000
10
NULL
241
2022-03-22 00:00:00.000
1
F1
270
2022-03-24 00:00:00.000
10
F1
273
2022-03-24 00:00:00.000
1
F1
308
2022-03-25 00:00:00.000
10
F1
But I need a result like this:
ID
Date
Event
Flow
4
2022-02-07 00:00:00.000
1
F1
44
2022-02-08 00:00:00.000
10
F1
47
2022-02-09 00:00:00.000
1
F2
72
2022-02-10 00:00:00.000
10
F2
75
2022-02-10 00:00:00.000
1
F3
97
2022-02-11 00:00:00.000
10
F3
100
2022-02-11 00:00:00.000
1
NULL
113
2022-02-28 00:00:00.000
1
F4
217
2022-03-04 00:00:00.000
10
F4
235
2022-03-22 00:00:00.000
10
NULL
241
2022-03-22 00:00:00.000
1
F5
270
2022-03-24 00:00:00.000
10
F5
273
2022-03-24 00:00:00.000
1
F6
308
2022-03-25 00:00:00.000
10
F6
I tried with a CTE, but I'm getting errors...
Thanks
This seems to work. I've copied your desired output as my input sample data just to show that my new column matches your Desired one, and also a couple of other renames for keywords:
declare #t table (ID int, DateOf datetime, EventNo int, DesiredFlow varchar(7))
insert into #t(ID,DateOf,EventNo,DesiredFlow) values
(4 ,'2022-02-07T00:00:00.000',1 ,'F1'),
(44 ,'2022-02-08T00:00:00.000',10 ,'F1'),
(47 ,'2022-02-09T00:00:00.000',1 ,'F2'),
(72 ,'2022-02-10T00:00:00.000',10 ,'F2'),
(75 ,'2022-02-10T00:00:00.000',1 ,'F3'),
(97 ,'2022-02-11T00:00:00.000',10 ,'F3'),
(100 ,'2022-02-11T00:00:00.000',1 ,NULL),
(113 ,'2022-02-28T00:00:00.000',1 ,'F4'),
(217 ,'2022-03-04T00:00:00.000',10 ,'F4'),
(235 ,'2022-03-22T00:00:00.000',10 ,NULL),
(241 ,'2022-03-22T00:00:00.000',1 ,'F5'),
(270 ,'2022-03-24T00:00:00.000',10 ,'F5'),
(273 ,'2022-03-24T00:00:00.000',1 ,'F6'),
(308 ,'2022-03-25T00:00:00.000',10 ,'F6')
;With Neighbours as (
select
*,
LEAD(EventNo,1,NULL) OVER (ORDER BY ID) as Successor,
LAG(EventNo,1,NULL) OVER (ORDER BY ID) as Predecessor
from
#t t
), NoStragglers as (
select
*
from
Neighbours
where
(EventNo = 1 and Successor = 10) or
(EventNo = 10 and Predecessor = 1)
), Ordered as (
select
*, ROW_NUMBER() OVER (PARTITION BY EventNo ORDER BY ID) as rn
from NoStragglers
)
select
t.*,'F' + (CONVERT(varchar(10),o.rn)) as ActualFlow
from
#t t
left join
Ordered o
on
t.Id = o.Id
Hopefully you can see how each CTE builds from the previous one (either by inspection or changing the final select to pull one one of the earlier CTEs instead).
Result:
ID DateOf EventNo DesiredFlow ActualFlow
----------- ----------------------- ----------- ----------- -----------
4 2022-02-07 00:00:00.000 1 F1 F1
44 2022-02-08 00:00:00.000 10 F1 F1
47 2022-02-09 00:00:00.000 1 F2 F2
72 2022-02-10 00:00:00.000 10 F2 F2
75 2022-02-10 00:00:00.000 1 F3 F3
97 2022-02-11 00:00:00.000 10 F3 F3
100 2022-02-11 00:00:00.000 1 NULL NULL
113 2022-02-28 00:00:00.000 1 F4 F4
217 2022-03-04 00:00:00.000 10 F4 F4
235 2022-03-22 00:00:00.000 10 NULL NULL
241 2022-03-22 00:00:00.000 1 F5 F5
270 2022-03-24 00:00:00.000 10 F5 F5
273 2022-03-24 00:00:00.000 1 F6 F6
308 2022-03-25 00:00:00.000 10 F6 F6
Which seems to match.
Check this,
create table #temp(id int,dates datetime,Events int)
insert into #temp(id,dates,events) values
(4 ,'2022-02-07 00:00:00.000', 1 )
,(44 ,'2022-02-08 00:00:00.000', 10 )
,(47 ,'2022-02-09 00:00:00.000', 1 )
,(72 ,'2022-02-10 00:00:00.000', 10 )
,(75 ,'2022-02-10 00:00:00.000', 1 )
,(97 ,'2022-02-11 00:00:00.000', 10 )
,(100 ,'2022-02-11 00:00:00.000', 1 )
,(113 ,'2022-02-28 00:00:00.000', 1 )
,(217 ,'2022-03-04 00:00:00.000', 10 )
,(235 ,'2022-03-22 00:00:00.000', 10 )
,(241 ,'2022-03-22 00:00:00.000', 1 )
,(270 ,'2022-03-24 00:00:00.000', 10 )
,(273 ,'2022-03-24 00:00:00.000', 1 )
,(308 ,'2022-03-25 00:00:00.000', 10 )
WITH CTE
AS (SELECT Id,
Dates,
Events,
CASE
WHEN Events = 1
AND LEAD(Events) OVER(
ORDER BY ID) = 10
THEN id
WHEN Events = 10
AND LAG(Events) OVER(
ORDER BY ID) = 1
THEN LAG(id) OVER(
ORDER BY ID)
ELSE NULL
END AS Flow
FROM #temp),
CtE1
AS (SELECT *,
DENSE_RANK() OVER(
ORDER BY flow) rn
FROM CTe
WHERE flow IS NOT NULL
UNION ALL
SELECT *,
NULL
FROM CTE
WHERE flow IS NULL)
SELECT id,
dates,
events,
CASE
WHEN rn IS NOT NULL
THEN concat('F', rn)
ELSE NULL
END Flow
FROM cte1
ORDER BY id;
drop table #temp
You can use cascading subqueries to assign a ROW_NUMBER() based on Flow values that are NOT NULL:
SELECT d.Id,
d.Date,
d.Event,
CASE WHEN b.rn IS NULL THEN NULL
ELSE CONCAT('F', b.rn)
END AS Flow
FROM (SELECT
Id,
Date,
Event,
Flow,
ROW_NUMBER() OVER (PARTITION BY Event ORDER BY Id ASC) as rn
FROM (SELECT
Id,
Date,
Event,
CASE WHEN Event = 1 AND LEAD(Event) OVER (ORDER BY Id) = 10 THEN 1
WHEN Event = 10 AND LAG(Event) OVER (ORDER BY Id) = 1 THEN 1
ELSE 0
END as Flow
FROM SystemEventsDiary WHERE Event IN (1, 10)
) a WHERE Flow = 1) b
RIGHT JOIN SystemEventsDiary d ON b.id = d.Id
ORDER BY d.Id ASC
Result:
Id
Date
Event
Flow
4
2022-02-07 00:00:00.000
1
F1
44
2022-02-08 00:00:00.000
10
F1
47
2022-02-09 00:00:00.000
1
F2
72
2022-02-10 00:00:00.000
10
F2
75
2022-02-10 00:00:00.000
1
F3
97
2022-02-11 00:00:00.000
10
F3
100
2022-02-11 00:00:00.000
1
NULL
113
2022-02-28 00:00:00.000
1
F4
217
2022-03-04 00:00:00.000
10
F4
235
2022-03-22 00:00:00.000
10
NULL
241
2022-03-22 00:00:00.000
1
F5
270
2022-03-24 00:00:00.000
10
F5
273
2022-03-24 00:00:00.000
1
F6
308
2022-03-25 00:00:00.000
10
F6
db<>fiddle here.

Subtract depletion And Limit for SUM

First I'm using AdventureWork2019 as a reference
I have a query where I'm joining 5 Tables
USE [AdventureWorks2019]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
Alter PROCEDURE dbo.TestLocation
#UseDate DateTime
AS
BEGIN
SET NOCOUNT ON;
SELECT prodID
,SUM(PurchQty) AS TotalPurchase
,SUM(SalesQty) AS TotalSell
,StartDate
from (
SELECT DISTINCT WO.ProductID AS prodID
, StartDate
,WO.OrderQty AS PurchQty
,SOD.OrderQty AS SalesQty
FROM Sales.SalesOrderDetail SOD
LEFT JOIN Production.WorkOrderRouting WOR ON WOR.ProductID = SOD.ProductID
--LEFT JOIN Production.Location PL ON PL.LocationID = WOR.LocationID
--The above Join is the one for the locationID and it's working Fine
LEFT JOIN Production.WorkOrder WO ON WO.ProductID = SOD.ProductID
FULL OUTER JOIN Purchasing.PurchaseOrderDetail POD ON POD.ProductID = SOD.ProductID
WHERE StartDate = #UseDate
-- AND PL.LocationID >= 10
) Test3
Group by prodID,StartDate
order by prodID ASC, StartDate
END
GO
EXEC TestLocation '2011-07-02 00:00:00.000'
Output(sample):
prodID TotalPurc TotalSell StartDate
717 8 36 2011-07-02 00:00:00.000
730 9 47 2011-07-02 00:00:00.000
744 2 3 2011-07-02 00:00:00.000
747 12 21 2011-07-02 00:00:00.000
749 5 15 2011-07-02 00:00:00.000
761 16 138 2011-07-02 00:00:00.000
775 26 91 2011-07-02 00:00:00.000
777 12 78 2011-07-02 00:00:00.000
802 6 21 2011-07-02 00:00:00.000
804 40 60 2011-07-02 00:00:00.000
806 16 138 2011-07-02 00:00:00.000
807 24 23 2011-07-02 00:00:00.000
810 21 28 2011-07-02 00:00:00.000
811 6 21 2011-07-02 00:00:00.000
813 8 37 2011-07-02 00:00:00.000
817 21 28 2011-07-02 00:00:00.000
And another Table For LocationID (as a warehouse)
SELECT LocationID,CostRate,Availability
FROM Production.Location
WHERE LocationID >= 10
order by CostRate ASC
LocationID CostRate Availability
50 12.25 120.00
60 12.25 120.00
30 14.50 120.00
40 15.75 120.00
45 18.00 80.00
10 22.50 96.00
20 25.00 108.00
What I want to do is to take each LoactionId and ProdID and take TotalPurc to the location and decrement the quantity in the Availability column, each TotalSell will increment the Availability column. The max Availability quantity is 130.
If all locations have no Available quantity that is the Available is 0 for all locations then it will stop.
the above will work with the date specified as you can check the query and run it if you have
AdventureWork2019
simple output to check how I want the data to be:
prodID TotalPurc TotalSell StartDate
717 8 36 2011-07-02 00:00:00.000
730 9 47 2011-07-02 00:00:00.000
744 2 3 2011-07-02 00:00:00.000
747 12 21 2011-07-02 00:00:00.000
749 5 15 2011-07-02 00:00:00.000
LocationID CostRate Availability
50 12.25 120.00
60 12.25 120.00
30 14.50 120.00
40 15.75 120.00
45 18.00 80.00
10 22.50 96.00
20 25.00 108.00
Output :
prodID TotalPurc TotalSell StartDate LocationID Availability Remaining
717 8 36 2011-07-02 00:00:00.000 50 130 18
717 8 36 2011-07-02 00:00:00.000 60 130 8
717 8 36 2011-07-02 00:00:00.000 30 128 0
--what happened above is that I took the (120-8) = 112 then 112+36 = 148 we only can use 130 then the remaining is 18 then we took the next `LocationID` with the least Cost (120+18 = 138 we can use 130 so we took the 8) and used it in the next `LocationID`
730 9 47 2011-07-02 00:00:00.000 30 130 36
730 9 47 2011-07-02 00:00:00.000 40 130 26
730 9 47 2011-07-02 00:00:00.000 45 106 0
744 2 3 2011-07-02 00:00:00.000 45 107 0
747 12 21 2011-07-02 00:00:00.000 45 116 0
749 5 15 2011-07-02 00:00:00.000 45 126 0
--the above is the same as the first 3 rows we subtract and add to the availability
The other condition is that if all locations reached 0 or 130 then stop
How can I do that in SQL Server? I tried using CTE but didn't work well with me and tried the cursor which I think is the best for this kind of thing but didn't achieve anything.
Thank you in advance
Edit :
ALTER FUNCTION GetStockMovment
(
-- Add the parameters for the function here
#ForDate Datetime
)
RETURNS #Sums TABLE (
RemoveQTY Numeric(24, 7),
ADDQTY Numeric(24, 7)
)
AS
BEGIN
Declare #WoSum Numeric(24, 7),
#SODSUM Numeric(24, 7),
#WORSum Numeric(24, 7),
#PODSum Numeric(24, 7)
select #SODSUM = SUM(SOD.OrderQty) from Sales.SalesOrderDetail SOD
INNER JOIN Sales.SalesOrderHeader SOH ON SOD.SalesOrderID = SOH.SalesOrderID
where SOH.OrderDate = #ForDate
select #WoSum = sum(orderQty) from Production.WorkOrder
where StartDate = #ForDate
select #PODSum = sum(POD.OrderQty) from Purchasing.PurchaseOrderDetail POD
INNER JOIN Purchasing.PurchaseOrderHeader POH ON POD.PurchaseOrderID = POH.PurchaseOrderID
where POH.OrderDate = #ForDate
select #WoSum = sum(WO.OrderQty) from Production.WorkOrder WO
where WO.DueDate = #ForDate
INSERT INTO #Sums (RemoveQTY,ADDQTY)
SELECT isnull(#SODSUM,0) + isnull(#WORSum,0) , isnull(#PODSum,0) + isnull(#WoSum,0)
RETURN;
END;
GO
select * from dbo.GetStockMovment ('2014-05-26 00:00:00.000')
Output:
RemoveQTY ADDQTY
189.0000000 5334.0000000
You should use LAG or LEAD function.
https://learn.microsoft.com/en-us/sql/t-sql/functions/lead-transact-sql?view=sql-server-ver15
https://learn.microsoft.com/en-us/sql/t-sql/functions/lag-transact-sql?view=sql-server-ver15

T-SQL Join two tables where the join condition is dependant on values in both tables

I have a query which combines data from two tables.
Policy table
PolicyID PolicyNumber PolicyStartDate
48 FCO100009 2015-06-01 00:00:00.000
49 FCO100009 2016-06-01 00:00:00.000
Claim Table
ClaimID ClaimReference PolicyNumber IncidentDatetime NotificationDatetime Version
30 287 FCO100009 2015-11-06 00:00:00.000 2015-11-27 00:00:00.000 4. Claim - Incident Date
223 259 FCO100009 2015-11-03 00:00:00.000 2015-11-20 00:00:00.000 4. Claim - Incident Date
1367 988 FCO100009 2016-04-15 00:00:00.000 2016-04-21 00:00:00.000 4. Claim - Incident Date
1561 1859 FCO100009 2016-09-14 00:00:00.000 2016-09-19 00:00:00.000 4. Claim - Incident Date
1741 443275 FCO100009 2016-05-11 00:00:00.000 2016-05-12 00:00:00.000 4. Claim - Incident Date
1742 991 FCO100009 2016-04-20 00:00:00.000 2016-04-21 00:00:00.000 4. Claim - Incident Date
2038 287 FCO100009 2015-11-06 00:00:00.000 2015-11-27 00:00:00.000 5. Claim - Notification Date
3744 259 FCO100009 2015-11-03 00:00:00.000 2015-11-20 00:00:00.000 5. Claim - Notification Date
3745 991 FCO100009 2016-04-20 00:00:00.000 2016-04-21 00:00:00.000 5. Claim - Notification Date
4502 1859 FCO100009 2016-09-14 00:00:00.000 2016-09-19 00:00:00.000 5. Claim - Notification Date
4639 988 FCO100009 2016-04-15 00:00:00.000 2016-04-21 00:00:00.000 5. Claim - Notification Date
6600 443275 FCO100009 2016-05-11 00:00:00.000 2016-05-12 00:00:00.000 5. Claim - Notification Date
There are 2 records for the Policy with different Policy Start Dates and a 2 versions of each claim record where the Version field is either Claim Incident Date or Claim Notification Date.
What I am attempting to accomplish is joining the two tables on PolicyNumber and then setting the PolicyStartDate value in the results to be the maximum value from Policy.PolicyStartDate where the PolicyStartDate is less than the NotificationDate when Version = NotificationDate OR PolicyStartDate is less than the Incident Date when Version = IncidentDate.
Please note that this is using financial NOT Calendar years and in this case the year of account runs from April to March.
Here is my current query which doesn't produce the correct answer:
SELECT cds.ClaimID,
cds.ClaimReference,
p.policyID,
p.PolicyStartDate,
cds.IncidentDatetime,
cds.NotificationDatetime,
cds.[Version]
FROM dbo.ClaimDataStaging cds
INNER JOIN dbo.[Policy] p
ON p.PolicyNumber = cds.PolicyNumber
AND p.PolicyStartDate < CASE WHEN cds.[Version] = '4. Claim - Incident Date' THEN cds.IncidentDatetime
WHEN cds.[Version] = '5. Claim - Notification Date' THEN cds.NotificationDatetime END
WHERE cds.PolicyNumber = 'FCO100009'
ORDER BY cds.[Version], cds.ClaimReference;
GO
Any help or advice much appreciated.
As far as I understood your question and your problem (duplicates caused by condition on date < date which catches former policy too), you can try this query too.
It use LEAD() function to calculate a sort of Enddate (I used IS NULL to to catch last policy, but you can change it adapting to your needs).
I moved the CASE in an inner query to avoid repeating of it in the WHERE clause.
SELECT cds.ClaimID,
cds.ClaimReference,
p.policyID,
p.PolicyStartDate,
cds.IncidentDatetime,
cds.NotificationDatetime,
cds.[Version]
FROM (SELECT ClaimID, ClaimReference, IncidentDatetime,NotificationDatetime,[Version], PolicyNumber
, CASE WHEN [Version] = '4. Claim - Incident Date' THEN IncidentDatetime
WHEN [Version] = '5. Claim - Notification Date' THEN NotificationDatetime END AS CheckDate
FROM dbo.ClaimDataStaging) cds
INNER JOIN (SELECT policyID, PolicyNumber, PolicyStartDate
, LEAD(PolicyStartDate) OVER (PARTITION BY PolicyNumber ORDER BY PolicyStartDate) AS PolicyEndDate FROM dbo.Policy ) p
ON p.PolicyNumber = cds.PolicyNumber
AND p.PolicyStartDate < CheckDate
AND (p.PolicyEndDate IS NULL OR p.PolicyEndDate>=CheckDate)
WHERE cds.PolicyNumber = 'FCO100009'
ORDER BY cds.[Version], cds.ClaimReference;
Output:
+---------+----------------+----------+-------------------------+-------------------------+-------------------------+------------------------------+
| ClaimID | ClaimReference | policyID | PolicyStartDate | IncidentDatetime | NotificationDatetime | Version |
+---------+----------------+----------+-------------------------+-------------------------+-------------------------+------------------------------+
| 223 | 259 | 48 | 2015-06-01 00:00:00.000 | 2015-11-03 00:00:00.000 | 2015-11-20 00:00:00.000 | 4. Claim - Incident Date |
| 30 | 287 | 48 | 2015-06-01 00:00:00.000 | 2015-11-06 00:00:00.000 | 2015-11-27 00:00:00.000 | 4. Claim - Incident Date |
| 1367 | 988 | 48 | 2015-06-01 00:00:00.000 | 2016-04-15 00:00:00.000 | 2016-04-21 00:00:00.000 | 4. Claim - Incident Date |
| 1742 | 991 | 48 | 2015-06-01 00:00:00.000 | 2016-04-20 00:00:00.000 | 2016-04-21 00:00:00.000 | 4. Claim - Incident Date |
| 1561 | 1859 | 49 | 2016-06-01 00:00:00.000 | 2016-09-14 00:00:00.000 | 2016-09-19 00:00:00.000 | 4. Claim - Incident Date |
| 1741 | 443275 | 48 | 2015-06-01 00:00:00.000 | 2016-05-11 00:00:00.000 | 2016-05-12 00:00:00.000 | 4. Claim - Incident Date |
| 3744 | 259 | 48 | 2015-06-01 00:00:00.000 | 2015-11-03 00:00:00.000 | 2015-11-20 00:00:00.000 | 5. Claim - Notification Date |
| 2038 | 287 | 48 | 2015-06-01 00:00:00.000 | 2015-11-06 00:00:00.000 | 2015-11-27 00:00:00.000 | 5. Claim - Notification Date |
| 4639 | 988 | 48 | 2015-06-01 00:00:00.000 | 2016-04-15 00:00:00.000 | 2016-04-21 00:00:00.000 | 5. Claim - Notification Date |
| 3745 | 991 | 48 | 2015-06-01 00:00:00.000 | 2016-04-20 00:00:00.000 | 2016-04-21 00:00:00.000 | 5. Claim - Notification Date |
| 4502 | 1859 | 49 | 2016-06-01 00:00:00.000 | 2016-09-14 00:00:00.000 | 2016-09-19 00:00:00.000 | 5. Claim - Notification Date |
| 6600 | 443275 | 48 | 2015-06-01 00:00:00.000 | 2016-05-11 00:00:00.000 | 2016-05-12 00:00:00.000 | 5. Claim - Notification Date |
+---------+----------------+----------+-------------------------+-------------------------+-------------------------+------------------------------+
Based on the suggestions received, I was able to adjust my query to provide the required result. Here is my final code for reference:
SELECT DISTINCT
cds.ClaimID,
MAX(p.PolicyID) OVER (PARTITION BY cds.PolicyNumber) AS PolicyID,
MAX(p.PolicyStartDate) OVER (PARTITION BY cds.PolicyNumber) AS
PolicyStartDate, cds.ClaimKey, cds.ClaimReference, cds.ClaimStatus,
cds.IncidentDatetime, cds.NotificationDatetime, cds.UW_Date,
cds.IncidentType, cds.IncidentDescription, cds.OwnDamagePaid,
cds.OwnDamageReserve, cds.OwnDamageIncurred, cds.TPDamagePaid,
cds.TPDamageReserve, cds.TPDamageIncurred,
cds.BodilyInjuryPaid, cds.BodilyInjuryReserve,
cds.BodilyInjuryIncurred, cds.TotalPaid, cds.TotalReserve,
cds.EstimatedRecovery, cds.ActualRecovery, cds.TotalIncurred, cds.TotalIncurredBand,
CONVERT(VARCHAR(16), 'Current Period') AS TimeView, 1 AS ClaimCount, CONVERT(VARCHAR(48), [Version]) AS [Version]
FROM dbo.ClaimDataStaging cds
INNER JOIN dbo.UW_Calendar u
ON u.UW_Date = cds.UW_Date
LEFT OUTER JOIN dbo.[Policy] p
ON p.PolicyNumber = cds.PolicyNumber
AND p.PolicyStartDate <= CASE
WHEN cds.[Version] = '4. Claim - Incident Date' THEN cds.IncidentDatetime
WHEN cds.[Version] = '5. Claim - Notification Date' THEN cds.NotificationDatetime
END;
GO
I think you're looking for something like the query below. It will give you the max policy number based on the filter you had for the dates.
SELECT cds.ClaimID,
cds.ClaimReference,
p.policyID,
p.PolicyStartDate,
cds.IncidentDatetime,
cds.NotificationDatetime,
cds.[Version]
FROM dbo.ClaimDataStaging cds
CROSS APPLY (
SELECT PolicyStartDate = MAX(fp.PolicyStartDate)
FROM dbo.[Policy] fp
WHERE fp.PolicyNumber = cds.PolicyNumber
AND ((fp.PolicyStartDate < cds.IncidentDatetime AND cds.[Version] = '4. Claim - Incident Date')
OR (fp.PolicyStartDate < cds.NotificationDatetime AND cds.[Version] = '5. Claim - Notification Date')) sp
INNER JOIN dbo.[Policy] p ON p.PolicyNumber = cds.PolicyNumber AND p.PolicyStartDate = sp.PolicyStartDate
WHERE cds.PolicyNumber = 'FCO100009'
ORDER BY cds.[Version], cds.ClaimReference;
GO

How to create a date range from a list of dates

I've tried searching for an answer to my question but all the scenarios that have been covered previously are slightly different. Apologies If I've missed one that does answer this.
I have a table that looks like this:
ID Date
35 2015-06-01
35 2015-06-02
35 2015-06-03
35 2015-06-06
40 2015-06-07
40 2015-06-08
40 2015-06-09
40 2015-06-10
40 2015-06-13
35 2015-06-14
35 2015-06-15
35 2015-06-16
35 2015-06-17
And I would like to get it in the form:
ID DateFrom DateTo
35 2015-06-01 2015-06-07
40 2015-06-07 2015-06-14
35 2015-06-14 2015-06-18
However, every solution that I can think of or have seen (row_number(), min / max, lag etc) only returns the following
ID DateFrom DateTo
35 2015-06-01 2015-06-18
40 2015-06-07 2015-06-14
i.e the date range for ID 35 is taking the min and max of the dates from the first table. It seems like this should be easy but I'm completely stuck.
Thanks,
Tom
You can do this using ROW_NUMBER with MIN and MAX:
SQL Fiddle
WITH CteGrp AS(
SELECT *,
grp = ROW_NUMBER() OVER(ORDER BY Date)
- ROW_NUMBER() OVER(PARTITION BY ID ORDER BY Date)
FROM tbl
)
SELECT
ID,
DateFrom = MIN([Date]),
DateTo = MAX([Date])
FROM CteGrp
GROUP BY ID, grp
ORDER BY DateFrom
RESULT
| ID | DateFrom | DateTo |
|----|------------|------------|
| 35 | 2015-06-01 | 2015-06-06 |
| 40 | 2015-06-07 | 2015-06-13 |
| 35 | 2015-06-14 | 2015-06-17 |

Handle condition in select statement

I have a table like this:
customer:
customerID joineddate
111 2004-12-10 00:00:00.000
111 2004-12-10 00:00:00.000
111 2004-12-10 00:00:00.000
211 2004-12-10 00:00:00.000
231 2004-12-10 00:00:00.000
231 2004-11-10 00:00:00.000
411 2008-12-10 00:00:00.000
531 2009-12-10 00:00:00.000
I have written the query from 2 tables where I do a join and get the result like the above. But I need to get the result like this where I need to input my condition and get the result like below.
customerID joineddate indicator
111 2004-12-10 00:00:00.000 3
211 2004-12-10 00:00:00.000 1
231 2004-12-10 00:00:00.000 1
231 2004-11-10 00:00:00.000 1
411 2008-12-10 00:00:00.000 1
531 2009-12-10 00:00:00.000 1
Having absolutely no clue what your other table is named or how it is related to the customer table, here is my best guess:
SELECT c.customerID, o.joineddate, indicator = COUNT(*)
FROM dbo.customer AS c
INNER JOIN dbo.[other table] AS o
ON c.CustomerID = o.CustomerID
GROUP BY c.customerID, o.joineddate;
Google for keyword
GROUP BY
and the
COUNT()
function.

Resources