I have a table like this:
Client Branch Amount Date
1 2 1500 1.1.14
1 2 1400 3.1.14
1 3 1500 1.1.14
1 4 300 7.1.14
1 5 1500 1.1.14
------------------------------
2 2 300 1.1.14
2 2 300 1.1.14
2 5 300 1.1.14
2 3 400 4.1.14
------------------------------
3 2 300 1.1.14
3 2 300 1.1.14
3 5 300 1.1.14
3 5 300 1.1.14
3 3 400 4.1.14
4 2 300 1.1.14
4 2 300 1.1.14
4 5 300 1.1.14
4 5 300 1.1.14
4 5 300 1.1.14
And my desired output should be like this:
Client Branch Amount Date Ind Loan_Distinct_Num
1 2 1500 1.1.14 0 1
1 2 1400 3.1.14 0 2
1 3 1500 1.1.14 1 1
1 4 300 7.1.14 0 3
1 5 1500 1.1.14 1 1
-------------------------------------------------
2 2 300 1.1.14 0 1
2 2 300 1.1.14 0 2
2 5 300 1.1.14 1 2
2 3 400 4.1.14 0 3
--------------------------------------------------
3 2 300 1.1.14 0 1
3 2 300 1.1.14 0 2
3 5 300 1.1.14 1 1
3 5 300 1.1.14 1 2
3 3 400 4.1.14 0 3
------------------------------------------------
4 2 300 1.1.14 0 1
4 2 300 1.1.14 0 2
4 5 300 1.1.14 1 1
4 5 300 1.1.14 1 2
4 5 300 1.1.14 0 3
So what am I trying to do? (Comment: Those records are just a sample data)
Well, those are the rules:
A client has moved from one branch to another in the same bank. The problem is that the branches were writing the data for him several times. I want to identify loans that are repeating. Two steps needed:
Step1 :
Assumption : Same_Amount + Same_Date + Diffrent Date ---> Ind = 1 on the records that are after the first raw.
How Ind field works?
For example:
In the partition for client = 1 the amount 1500 is reapting 3 times for same date and diffrent branches but only the two last records for this details will get a "1" value for Ind, the first will get Ind = 0 because it is not a repeting loan, it is the first time that a record with this amount and date appears in the data.
In case like client = 2 there were two records for branch = 2 and only one for branch = 5 so in this case I will assum that the last record for the branch = 2 was being repeted.
In case like client = 3 there were two records in branch = 2 and two records for branch = 5 so in this case i will assume that both of the loans from branch 2 was repeted.
In Case client = 4, well it will be the same like client 3 but there was another record but I will consider it a new one because I have no extra past loan to communicate with her.
Step 2: I want to create my own distinct loan number for each client
Any help on how to approach for solving this nor simple problem?
comment : sql-server 2008.
First - set up your data into a table. I've added an identity column ID, so we have something to order by - you specified in a comment that your data was in a specific order.
declare #data table (ID int identity(1,1), Client int, Branch int, Amount int, [Date] date);
insert into #data values
(1,2, 1500,'2014-01-01'),
(1,2, 1400,'2014-03-01'),
(1,3, 1500,'2014-01-01'),
(1,4, 300,'2014-07-01'),
(1,5, 1500,'2014-01-01'),
(2,2, 300,'2014-01-01'),
(2,2, 300,'2014-01-01'),
(2,5, 300,'2014-01-01'),
(2,3, 400,'2014-04-01'),
(3,2, 300,'2014-01-01'),
(3,2, 300,'2014-01-01'),
(3,5, 300,'2014-01-01'),
(3,5, 300,'2014-01-01'),
(3,3, 400,'2014-04-01'),
(4,2, 300,'2014-01-01'),
(4,2, 300,'2014-01-01'),
(4,5, 300,'2014-01-01'),
(4,5, 300,'2014-01-01'),
(4,5, 300,'2014-01-01');
Here is where we do the query:
--In the first cte, we take all the data, and partition it up into individual loans (partition by Client, Amount, Date).
with cte1 as (
select *, ROW_NUMBER() over (partition by Client, Amount, Date order by ID) as rowno from #data
), cte2 as (
--in this cte, we get a list of distinct loans. We will use another rownumber in a bit to find our Loan_Distinct_Num
select distinct Client, Amount, [Date] from #data
)
select cte1.Client, cte1.Branch, cte1.Amount, cte1.[Date]
-- If rowno = 1, it's the first instance of that combination
, case when rowno = 1 then 0 else 1 end as ind
, b.Loan_Distinct_Num
from cte1
left join (select cte2.*, ROW_NUMBER() over (partition by Client order by [Date]) as Loan_Distinct_Num
-- This is where our distinct loan number comes from
from cte2
) as b
on b.Client = cte1.Client and b.Amount = cte1.Amount and b.[Date] = cte1.[Date]
order by ID
Here's an answer if ind should only be 1 if exists a previous record with a different branch # (see row 7). Also, uses dense_rank to group loans by amount/date in loan_distinct_num. The logic seems more complex for that column - if this is a one-time fix, I might use a cursor to loop through the table and apply some more complex logic to populate that one column, rather than try to calculate it in a query.
-- sample data
declare #data table (ID int identity(1,1), Client int, Branch int, Amount int, [Date] date);
insert into #data values
(1,2, 1500,'2014-01-01'),
(1,2, 1400,'2014-03-01'),
(1,3, 1500,'2014-01-01'),
(1,4, 300,'2014-07-01'),
(1,5, 1500,'2014-01-01'),
(2,2, 300,'2014-01-01'),
(2,2, 300,'2014-01-01'),
(2,5, 300,'2014-01-01'),
(2,3, 400,'2014-04-01'),
(3,2, 300,'2014-01-01'),
(3,2, 300,'2014-01-01'),
(3,5, 300,'2014-01-01'),
(3,5, 300,'2014-01-01'),
(3,3, 400,'2014-04-01'),
(4,2, 300,'2014-01-01'),
(4,2, 300,'2014-01-01'),
(4,5, 300,'2014-01-01'),
(4,5, 300,'2014-01-01'),
(4,5, 300,'2014-01-01');
-- query
select client, branch, amount, date,
case when exists (select * from #data t2 where client = tbl.client and branch <> tbl.branch and amount = tbl.amount and date = tbl.date and id < tbl.id) then 1 else 0 end as ind,
DENSE_RANK() over (partition by client order by date, amount asc) as loan_disinct_num
from #data tbl
order by id;
I want to find rows (records) which have a specific vlaue (S) in a column (Type), and insert multiple rows (e.g. 2) based on that row in the same table.
For example, in tabe t1 below, I want for each row of type 'S', 2 rows be inserted with same ID and Price, new Counter value (no specific requirement for this filed, however the Counter for records with same ID must be different), and Type will be 'B'.
It means that when inserting 2 rows based on the first record in table below (1,1200,S,200), Counter value of the new records must be different from Counter values of the records with ID=1 already in the table (1200 and 1201). So, in the initial table there were three records with Type 'S', then in the final table, for each of those records, 2 new records with Type 'B' and a new Counter value is insrted:
ID Counter Type Price
------------------------
1 1200 S 200
1 1201 T 400
2 1200 T 500
3 1546 S 100
3 1547 S 70
4 2607 M 250
The output table t1 will be:
ID Counter Type Price
------------------------
1 1200 S 200
1 1202 B 200
1 1203 B 200
1 1201 T 400
2 1200 T 500
3 1546 S 100
3 1548 B 100
3 1549 B 100
3 1547 S 700
3 1550 B 700
3 1552 B 700
4 2607 M 250
You just have to play twice this command:
insert into epn
with w(max) as
(
select max(t.counter) from t -- useful to get max counter value
)
select t.id, w.max + rownum, 'B', t.price -- max + rownum then gives new values
from t, w
where t.type != 'B'; -- Avoid duplicating rows added 1st time
This gives:
1 1 1200 S 200
2 1 2617 B 200
3 1 2611 B 200
4 1 1201 T 400
5 1 2618 B 400
6 1 2612 B 400
7 2 1200 T 500
8 2 2613 B 500
9 2 2619 B 500
10 3 1547 S 70
11 3 2609 B 70
12 3 2615 B 70
13 3 1546 S 100
14 3 2614 B 100
15 3 2608 B 100
16 4 2607 M 250
17 4 2610 B 250
18 4 2616 B 250
You need an insert select statement:
insert into t1 (ID, Counter, Type, Price)
select ID, Counter+1, 'B', Price from t1 where Type = 'S'
union all
select ID, Counter+2, 'B', Price from t1 where Type = 'S';
EDIT: Here is a statement that matches your criteria mentioned in your remark below. It gets the maximum Counter per ID and adds the count # of the added entry to the ID (1, 2, 3, ...) to it.
insert into t1 (ID, Counter, Type, Price)
select
ID,
(select max(Counter) from t1 where ID = src.ID) + row_number() over (partition by ID order by Price) as new_counter,
'B' as Type,
Price
from
(
select ID, Price
from t1
join (select * from dual union all select * from dual) twice
where t1.Type = 'S'
) src;
CREATE SEQUENCE my_SEQ
INCREMENT BY 1
START WITH 1
MINVALUE 1
MAXVALUE 999999999
NOCYCLE
NOCACHE
NOORDER;
create table MY_TABLE1
( ID NUMBER,
counter number(20),
type varchar2(30),
price number
)
insert into my_table1 (id,counter,type,price)
values (my_SEQ.nextval,1200,'S',200);
insert into my_table1 (id,counter,type,price)
values (my_SEQ.nextval,1300,'B',311);
insert into my_table1 (id,counter,type,price)
values (my_SEQ.nextval,200,'S',110);
insert into my_table1 (id,counter,type,price)
values (my_SEQ.nextval,299,'B',329);
select * from my_table1
ID COUNTER TYPE PRICE
62 1200 S 200
63 1300 B 311
64 200 S 110
65 299 B 329
declare
cursor c1 is select * from My_table1 where type='B';
begin
for rec IN c1
loop
insert into my_table1 (id,counter,type,price)
values (my_SEQ.nextval,rec.counter+1,'Z',rec.price);
end loop;
end;
select * from my_table1
ID COUNTER TYPE PRICE
63 1300 B 311
65 299 B 329
64 200 S 110
62 1200 S 200
66 1301 Z 311
67 300 Z 329
6 rows selected.
So there in cursor select all rows where type is ='B' and insert them back with changed values a little! hope this helps. you could not use sequence but add rec.id+1
I have following tables:
UserMaster:
UserId Int, UserName Varchar(200),AddedBy Int
UserId EmpName AddedBy
1 admin 0
2 SubAdmin1 1
3 SubAdmin2 1
4 Vikas 2
5 Mohit 4
6 Atul 5
7 Vishal 6
8 Mani 3
9 Sunny 8
SalesMaster:
SalesId Int, UserId Int (FK_UserMaster_UserId) , Price Int
SalesId UserId Price
1 1 100
2 2 200
3 3 300
4 4 500
5 5 100
6 6 200
7 7 111
8 8 222
9 9 333
Case 1: Now I want the price total of all the users who are under the one particular user and its own price also.
Means If i consider UserId=1 , Then the price will be calculated for all users where Column value in AddedBy=1
and their lower level employees.
Means the total Price of users will be calulated for the users having UserId are: 1,2,3,4,5,6,7,8,9.
Case 2: Similarly, If i want to calculate the total price under UserId=3(SubAdmin2) then the total price from the salesMaster will be calculated for the Users having UserId are: 3,8,9
The Result of first Case should be:
UserId Price
1 2066
The Result of Second Case should be:
UserId Price
3 300+222+333
Please Help
Thanks & Regards
Nitin
with cte as (
select #UserId as UserId
union all
select um.UserId
from UserMaster as um
inner join cte as c on c.UserId = um.AddedBy
)
select sum(s.Price)
from cte as c
inner join SalesMaster as s on s.UserId = c.UserId
sql fiddle demo