Reputation: 11
This question has bothered me for most of the day, just can't figure it out, and I don't really know which keywords to google for.
Let's say I have policies and their date, and I want to know if the policy falls within the first year since its inception or later years. it will have to find the earliest date for each policy, and then return 1 if the future date is within 1 year of the original date.
I know that we need to use for while statements but I don't know how to begin.
Thanks
For example:
+--------+-----------+
| Policy | Date |
+--------+-----------+
| CC1002 | 5/1/2012 |
| CC1002 | 6/1/2012 |
| CC1002 | 7/1/2012 |
| CC1002 | 8/1/2012 |
| CC1002 | 9/1/2012 |
| CC1002 | 10/1/2012 |
| CC1002 | 11/1/2012 |
| CC1002 | 12/1/2012 |
| CC1002 | 1/1/2013 |
| CC1002 | 2/1/2013 |
| CC1002 | 3/1/2013 |
| CC1002 | 4/1/2013 |
| CC1002 | 5/1/2013 |
| CC1002 | 6/1/2013 |
| CC1002 | 7/1/2013 |
| CC1002 | 8/1/2013 |
| CC1008 | 5/1/2012 |
| CC1008 | 6/1/2013 |
+--------+-----------+
Results
+--------+-----------+-------------------+
| Policy | Date | YearfromInception |
+--------+-----------+-------------------+
| CC1002 | 5/1/2012 | 1 |
| CC1002 | 6/1/2012 | 1 |
| CC1002 | 7/1/2012 | 1 |
| CC1002 | 8/1/2012 | 1 |
| CC1002 | 9/1/2012 | 1 |
| CC1002 | 10/1/2012 | 1 |
| CC1002 | 11/1/2012 | 1 |
| CC1002 | 12/1/2012 | 1 |
| CC1002 | 1/1/2013 | 1 |
| CC1002 | 2/1/2013 | 1 |
| CC1002 | 3/1/2013 | 1 |
| CC1002 | 4/1/2013 | 1 |
| CC1002 | 5/1/2013 | 2 |
| CC1002 | 6/1/2013 | 2 |
| CC1002 | 7/1/2013 | 2 |
| CC1002 | 8/1/2013 | 2 |
| CC1008 | 5/1/2012 | 1 |
| CC1008 | 6/1/2013 | 2 |
+--------+-----------+-------------------+
Solved. This community is great!
Upvotes: 0
Views: 93
Reputation: 70513
In SQL you don't use loops -- SQL works on sets. In this case you want to get the set of all starting dates for policies and then join that back to the original table to get your results. Like this:
SELECT mytable.policy,
(datediff(m,sub.inception,mytable.PolicyDate)/12)+1 as yearfrominception
FROM mytable
JOIN (
SELECT Policy, Min(PolicyDate) as inception
FROM mytable
GROUP BY Policy
) as sub ON mytable.Policy = sub.Policy
Upvotes: 1
Reputation: 5745
Without subqueries:
CREATE TABLE #a
(
policy VARCHAR(100),
pDate DATE
)
INSERT INTO #a VALUES ('CC1002' ,'5/1/2012');
INSERT INTO #a VALUES ('CC1002', '6/1/2012');
INSERT INTO #a VALUES ('CC1002', '7/1/2012');
INSERT INTO #a VALUES ('CC1002', '8/1/2012');
INSERT INTO #a VALUES ('CC1002', '9/1/2012');
INSERT INTO #a VALUES ('CC1002', '10/1/2012');
INSERT INTO #a VALUES ('CC1002', '11/1/2012');
INSERT INTO #a VALUES ('CC1002', '12/1/2012');
INSERT INTO #a VALUES ('CC1002', '1/1/2013');
INSERT INTO #a VALUES ('CC1002', '2/1/2013');
INSERT INTO #a VALUES ('CC1002', '3/1/2013');
INSERT INTO #a VALUES ('CC1002', '4/1/2013');
INSERT INTO #a VALUES ('CC1002', '5/1/2013');
INSERT INTO #a VALUES ('CC1002', '6/1/2013');
INSERT INTO #a VALUES ('CC1002', '7/1/2013');
INSERT INTO #a VALUES ('CC1002', '8/1/2013');
INSERT INTO #a VALUES ('CC1008', '5/1/2012');
INSERT INTO #a VALUES ('CC1008', '6/1/2013');
SELECT a.policy ,
a.pDate ,
DATEDIFF(DAY, MIN(a.pDate) OVER (PARTITION BY a.policy), a.pDate)/365+ 1
FROM #a a
Upvotes: 1
Reputation: 865
You can do this a few different ways. You could set up a table with the MIN(Date) for each record:
WITH mindate (Policy, MinDate) as
(select Policy, min(Date) as MinDate
from mytable
group by Policy)
select
t1.Policy, t1.Date, DATEDIFF(year, t2.MinDate, t1.Date) + 1
from mytable t1 join mindate t2 on
t1.Policy = t2.Policy
I consider this the more universal SQL approach (without using temporary tables), but I believe you can replace the WITH derived table with an analytical function: MIN(Date) over (partition by Policy):
select Policy,
DATEDIFF(year, Min(Date) over (partition by Policy), Date) + 1
from mytable
That's obviously shorter, but less portable if you move away from SQL Server (although support is growing). If performance becomes an issue, indexes or temporary tables could speed things up.
Upvotes: 0
Reputation: 12154
assuming you mean to return, for each policy/date, the number of years since the policy first existed...
You'll have to figure out the year difference function, date stuff is highly platform dependent (and you seem to want SQL Server and MySQL) and generally need some tweaking. In my code, it would return 0 years for the first inception row, to which you would add +1 to get your results.
no whiles required. something like this should work:
select Policy
,Date
,function-datediff-in-years-for-your-db(
Date,
(select min(Date) from Policy_table s where s.Policy = Policy_table.Policy)
)
from Policy_table
Upvotes: 0