Click here to Skip to main content
15,908,172 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
I have a question about SQL Server.
Table : emp
SQL
id      |    name     | sdate       | edate 
1       |    abc      | 2003-11-13  | 2003-11-26
1       |    def      | 2000-04-08  | 2000-04-11
1       |    har      | 2003-08-01  | 2003-08-31
1       |    ka       | 2003-10-01  | 2003-10-31

Table: emp1
id  | locname | date    
1   | a       | 2003-10-01          
1   | b       | 2003-08-01              
1   | c       | 2000-04-08  
1   | d       | 2000-04-10

Here emp1 table related date column data fall between emp table sdate and edate.
If we got multiple then we need to consider min(date) related as old record and max(date) records as new records.
If we got single records follow condition then we need to consider same records as old and new record for that date.

If we don't have any records, then we need to consider emp1 table related columns data

Default values and based on this table I want output like below
SQL
id     |    name    |  sdate       |   edate    | Filter   |  locname   | date 
   1  |    abc     |    2003-11-13  |2003-11-26  | new      |   NA       | 1800-01-01(defaultdate)
   1  |    def      |   2000-04-08  |2000-04-11  | new      |   d        | 2000-04-10
   1  |    har      |   2003-08-01  |2003-08-31  | new      |   b        | 2003-08-01   
   1  |    ka         | 2003-10-01  |2003-10-31  | new      |   a        | 2003-10-01
   1  |    abc      |   2003-11-13  |2003-11-26  | old      |   NA       | 1800-01-01(defaultdate) 
   1  |    def      |   2000-04-08  |2000-04-11  | old      |   c        | 2000-04-08   
   1  |    har      |   2003-08-01  |2003-08-31  | old      |   b        | 2003-08-01
   1  |    ka         | 2003-10-01  |2003-10-31  | old      |   a        | 2003-10-01

I tried with this query:
SQL
select  
    max(date) as date, id, name,  
    sdate, edate, 'New' as Filter, locname   
from 
    (select   
         a.id, a.name, a.sdate, a.edate, 'New'as Filter,
         b.locname, b.date 
     from
         emp a  
     join  
         emp1 b on aid = b.id
                and CONVERT(VARCHAR(10), CAST(b.date AS DATE), 120) between CONVERT(VARCHAR(10), CAST(ltrim(rtrim(a.sdate)) AS DATE), 120) 
 and CASE WHEN coalesce(ltrim(rtrim(a.edate)),'') = '' THEN CONVERT(VARCHAR(10), CAST(getdate() AS DATE), 120)
 else CONVERT(VARCHAR(10), CAST(ltrim(rtrim(a.edate)) AS DATE), 120)  end 
       ) a
group by
    date, id, name, sdate, edate, 'New' as Filter, locname 

union all

select  min(date)as date ,id , name ,  sdate ,edate,'old'as Filter ,locname   from 
(select   a.id , a.name ,  a.sdate ,a.edate,'old'as Filter ,b.locname ,b.date from
  emp a  join  emp1 b on aid=b.id
  and CONVERT(VARCHAR(10), CAST(b.date AS DATE), 120) between  CONVERT(VARCHAR(10), CAST(ltrim(rtrim(a.sdate)) AS DATE), 120) 
 and  CASE WHEN coalesce(ltrim(rtrim(a.edate)),'') = '' THEN CONVERT(VARCHAR(10), CAST(getdate() AS DATE), 120)
 else CONVERT(VARCHAR(10), CAST(ltrim(rtrim(a.edate)) AS DATE), 120)  end 
  )a
 group by
 date ,id , name ,  sdate ,edate,'New'as Filter ,locname 


above query not qiven expected result .please tell me how to write query to achive this task in sql servr
Posted
Updated 20-Oct-15 22:10pm
v2

1 solution

First of all, do not store dates as strings, you will save yourself a lot of trouble. You code is hard to read because all of the conversions. Assuming dates are real dates you can do this:
SQL
with cte as
(
  select emp.id, emp1.id as id1
  from emp
  left join emp1 on emp1.[date] between emp.sdate and emp.edate
)
, cte2 as
(
  select id, min(id1) as id1, 'old' as filter
  from cte
  group by id
  
  union all
  
  select id, max(id1) as id1, 'new' as filter
  from cte
  group by id  
)
select * from cte2 -- join to emp and emp1 to get the other columns

I don't think the code needs much comment. If you need to convert strings to dates prepend all this with another cte where you do just that. Here is the SQL fiddle[^], have fun.

Edit - ids are not unique
If your ids are not unique and for example names are then you can do this:
SQL
with cte as
(
  select name, locname
  from emp
  left join emp1 on emp1.[date] between emp.sdate and emp.edate
)
, cte2 as
(
  select name, min(locname) as locname, 'old' as filter
  from cte
  group by name
  
  union all
  
  select name, max(locname) as locname, 'new' as filter
  from cte
  group by name 
)
select * from cte2

SQL fiddle[^]
 
Share this answer
 
v2
Comments
Member 12046790 21-Oct-15 13:15pm    
Hi,Given above query not working what I expected results.can you please tell me any other logic to get expected result .Thanks!
Tomas Takac 21-Oct-15 14:41pm    
You mean that I didn't give you the whole query? What you have to do is to join the result to emp and emp1 by id and id1 respectively to get your expected results.
Member 12046790 21-Oct-15 23:42pm    
Here In my source side data : id column same record have multiple that time .so above query not given expect result. may be if we have unique id its may work. but here data is different .Thanks!
Tomas Takac 22-Oct-15 2:27am    
If your names are unique, then you can use that. See my edit.
Member 12046790 22-Oct-15 8:37am    
here names also not a unique,this one also not given expected result .I given few records only.mainly we need to focus date columns not any other columns. because of all other columns may not be unique.when we check date fall between sdate and edate in emp table.that time if fall multiple records then we need to consider max(date) as new and min(date) as old.suppose only one date fall between sdate and edate from emp table then that date only we consder max(date)as new and same date as min(date) it as old records.Thanks!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900