Cumulative result of items for drawing - sql

I have a table ENG_Drawing.Its fields are
SELECT DrawingID,DrawingNumber,DrawingDescription FROM ENG_Drawing
DrawingID DrawingNumber DrawingDescription etc..
1131 R152-14-01-00-31 DU - 01 etc..
....
1200 R160-02-01-00-21 DU - 12 etc..
....
.....
....
1500 R156-01-01-00-11 DU - 00 etc..
....
.....
2993 R167-09-01-00-21 DU - 04 etc..
2994 R165-10-01-00-40 DU - 25 etc..
2995 R163-13-01-00-01 DU - 24 etc..
2996 R100-12-01-00-61 DU - 21 etc..
2997 R166-09-01-00-21 DU - 21 etc..
2998 R125-14-01-00-02 DU - 32 etc..
2999
3000
.
.
And detail table for drawing table is
DrawingID SeqNbr Drawing_f BOMQuantity ItemQty DrawingreferenceID ItemID
1131 7 0 2 0.574 1231
1131 9 1 4 null 1200 null
....
....
1200 14 1 8 0.560 1100 1555
1200 16 1 2 5.23 1500 1755
....
....
1500 18 0 2 4.350 2684
....
2993 5 0 2 0.061 2125
2993 6 0 2 1.592 1698
2993 7 0 2 2.500 1231
2993 9 1 4 null 1131 null
2993 16 1 2 null 1500 null
2993 18 0 2 4.350 2684
When I give DrawingID as 2993
In need output like this
ITEMID TOTALQTY
1231 9.592 //select((2*2.500) + (4*2*.574)) here (2*2.500)- is BOMQuantity(4)*ItemQty(2.500) for ItemID 2993 and (4*2*.574)- BOMQuantity of DrawingID 1131(4)*BOMQuantity of ItemID 1231 in DRawingID 1131(2)*ItemQty(.574)
1555 71.680 //select(4*4*8*.560) here 4-BOMQuantity of DrawingreferenceID 1131 in DrawingID 2993.Middle 4 is BOMQuantity of DrawingreferenceID 1200 in DrawingID 1131. 8 is BOMQuantity of ItemId 1555 in DrawingId 1200
1698 3.184 //select(2*1.592)
1755 50.944 //select(4*4*2*1.592)
2125 0.122 //select(2*0.061)
2684 0.122 //select((2*4.350)+(2*2*4.350))
ENG_Drawing_BOM contains subdrawings (DrawingreferenceID).they(DrawingreferenceID) have their values in ENG_Drawing table and also have items and subdrawings.
One drawing may have no of subdrawings and that subdrawings can have subdrawings and so on....
I need When i give DrawingID i need Item wise cumulation.The result should be is ITEMID,sum( BOMQuantity * ItemQty) as TOTALQTY.
The problem is,
For exmple
DrawingID has subdrawing with 4 BOMQuantity, i need TOTALQTY 4 times of that subdrawing(S1) items,
if that subdrawing has subdrawings(S2) with 6 BOMQuantity need 4 times of S1 items and 4*6 4 times of S2 items ...It will continue for its inner levels...
I finally need Overall ITEMID wise cumulation
here 2993 as main drawing.1131,1200,1500 are subdrawings and that subdrawings may have sub drawings.I need them also .
Any body????

#Suresh recheck your sample data,what is wrong in my query ?
Declare #drawing table( DrawingID int,SeqNbr int,Drawing_f int,BOMQuantity decimal(5,2),ItemQty decimal(6,3),DrawingreferenceID int,ItemID int)
insert into #drawing
select 1131 , 7, 0,2, 0.574,null,1231 union all
select 1131 , 9, 1,4,null ,1200,null union all
select 1200, 14, 1,8,0.560, 1100,1555 union all
select 1200, 16, 1,2,5.23 , 1500,1755 union all
select 1500, 18, 0,2,4.350, null,2684 union all
select 2993, 5, 0,2,0.061, null,2125 union all
select 2993, 6, 0,2,1.592, null,1698 union all
select 2993, 7, 0,2,2.500, null,1231 union all
select 2993, 9, 1,4,null , 1131,null union all
select 2993, 16, 1,2,null , 1500,null union all
select 2993, 18, 0 ,2,4.350, null,2684
--select * from #drawing
;with cte as
(select * ,1 roots from #drawing where DrawingID=2993
union all
select d.*,case when d.DrawingID=c.DrawingreferenceID then roots+1 else roots end from #drawing d inner join cte c on d.DrawingID=c.DrawingreferenceID
)
select * from cte
#Suresh if your last query is ok then make it accurate
with cte as
(
select d.* , 1 as Nooff,1 roots,d.DrawingID as 'MainDrawing' from ENG_Drawing_BOM d
union all
select d.*,c.BOMQuantity*C.Nooff as Nooff,case when d.DrawingID=c.DrawingreferenceID then roots+1 else roots end ,MainDrawing as 'MainDrawing'
from ENG_Drawing_BOM d inner join cte c on d.DrawingID=c.DrawingreferenceID
)
,CTE1 as
(
select
cte.MainDrawing,
cte.ItemID,
SUM(Nooff*cte.UnitWeight)as 'Wt',
SUM((TotalQty)*Nooff) as 'TotalQty'
from cte
where DrawingReferenceID is null AND MainDrawing = 2993
group by cte.ItemID, cte.MainDrawing
)
select
cte.MainDrawing,
cte.ItemID,
i.ItemDescription,
Wt,
TotalQty
from cte1
inner join STR_Item i on cte.ItemID = i.ItemID
where DrawingReferenceID is null AND MainDrawing = 2993
ORDER BY cte.ItemID

This is exact need ...derived from KumarHarsh reply.
with cte as
(
select d.* , 1 as Nooff,1 roots,d.DrawingID as 'MainDrawing' from ENG_Drawing_BOM d
union all
select d.*,c.BOMQuantity*C.Nooff as Nooff,case when d.DrawingID=c.DrawingreferenceID then roots+1 else roots end ,MainDrawing as 'MainDrawing' from ENG_Drawing_BOM d inner join cte c on d.DrawingID=c.DrawingreferenceID
)
select
cte.MainDrawing,
cte.ItemID,
i.ItemDescription,
SUM(Nooff*cte.UnitWeight)as 'Wt',
SUM((TotalQty)*Nooff) as 'TotalQty'
from cte
inner join STR_Item i on cte.ItemID = i.ItemID
where DrawingReferenceID is null AND MainDrawing = 2993
group by cte.ItemID,
cte.MainDrawing,
i.ItemDescription
ORDER BY cte.ItemID

Related

SQL Server - SUM and comma-separated values using GROUP BY clause

I have 2 tables:
NDEvent:
EventId EndTime
33 2020-10-23 15:00:00.000
33 2020-10-23 15:00:00.000
35 2020-10-21 03:30:00.000
35 2020-10-24 15:00:00.000
35 2020-10-25 15:00:00.000
34 2020-10-23 15:00:00.000
EventAppointment:
Id DocId EventId Amount
1 7647 34 10.00
2 7647 34 10.00
3 28531 33 20.00
4 7647 35 20.00
5 7647 35 100.00
6 7647 35 200.00
And I want result to be like this:
DocId EventId Amount Id
7647 34 20.00 1,2
28531 33 20.00 3
7647 35 320.00 4,5,6
What I have tried is:
select e.Amount,e.DoctorId,e.EventId,
Id= STUFF(
(SELECT DISTINCT ',' + CAST(e.Id as nvarchar(max))
from NDEvent nd
inner join EventAppointment e on nd.Id = e.EventId
where
GETDATE() > nd.EndTime
GROUP BY
e.Amount,e.DoctorId,e.EventId,e.Id
FOR XML PATH(''))
, 1, 1, ''
)
from NDEvent nd
inner join EventAppointment e on nd.Id = e.EventId
where
GETDATE() > nd.EndTime
GROUP BY
e.Amount,e.DoctorId,e.EventId
But it is not giving expected result.
Could anyone help with this query? Or point me to a right direction? Thank you.
It doesn't look like yo need to NDEvent table here at all (though I include it in the sample data). Just SUM and STRING_AGG against EventAppointment:
USE Sandbox
GO
WITH NDEvent AS(
SELECT *
FROM (VALUES(33,CONVERT(datetime,'2020-10-23T15:00:00.000')),
(33,CONVERT(datetime,'2020-10-23T15:00:00.000')),
(35,CONVERT(datetime,'2020-10-21T03:30:00.000')),
(35,CONVERT(datetime,'2020-10-24T15:00:00.000')),
(35,CONVERT(datetime,'2020-10-25T15:00:00.000')),
(34,CONVERT(datetime,'2020-10-23T15:00:00.000')))V(EventID,EndTime)),
EventAppointment AS(
SELECT *
FROM (VALUES(1,7647 ,34,10.00),
(2,7647 ,34,10.00),
(3,28531,33,20.00),
(4,7647 ,35,20.00),
(5,7647 ,35,100.00),
(6,7647 ,35,200.00))V(Id,DocId, EventID, Amount))
SELECT DocID,
EventID,
SUM(Amount) AS Amount,
STRING_AGG(Id,',') WITHIN GROUP (ORDER BY Id) AS IDs
FROM EventAppointment EA
GROUP BY DocId,
EventID;
Can be used in other data.
WITH Table1 AS(
SELECT EventId FROM NDEvent
GROUP BY EventId
),
Table2 AS(
SELECT e.DocId,e.EventId,e.Amount,
STUFF((
SELECT ',' + CAST(ee.Id as nvarchar)
FROM EventAppointment ee
where ee.EventId = e.EventId
GROUP BY ee.EventId,ee.Id
FOR XML PATH('')), 1, 1, '') AS Id
FROM Table1 t
LEFT OUTER JOIN EventAppointment e ON t.EventId = e.EventId
)
SELECT DocId,EventId,SUM(Amount) AS Amount,Id FROM Table2
GROUP BY DocId,EventId,Id

select rows with events related with another events in the same query column

I need to select rows with EventTypeID = 19 which does not have related EventtypeID = 21 LoggedOn exactly 4 minutes earlier for the same EmployeeID. Here's the query bellow and some raw output:
SELECT * FROM
(
SELECT rcp..EventLogEntries.EmployeeID, rcp..EventLogEntries.EventTypeID, rcp..EventLogEntries.TerminalID, rcp..EventLogEntries.LoggedOn
FROM rcp..EventLogEntries
WHERE rcp..EventLogEntries.terminalid = 3
UNION
SELECT viso..AccessUserPersons.UserExternalIdentifier, rcp..EventTypes.ID, rcp..Terminals.ID, viso..EventLogEntries.LoggedOn
FROM viso..EventLogEntries, viso..AccessUserPersons, rcp..Terminals, rcp..EventTypes
WHERE viso..EventLogEntries.LocationID = 10
AND viso..EventLogEntries.EventCode = 615
AND rcp..EventTypes.Code = 36
AND viso..EventLogEntries.PersonID = viso..AccessUserPersons.ID
AND viso..EventLogEntries.locationID = rcp..Terminals.TerminalTAID
) results
ORDER BY LoggedOn
EmployeeID EventTypeID TerminalID LoggedOn
273 19 3 2018-12-04 12:31:23.000
273 21 3 2018-12-04 12:34:18.000
483 19 3 2018-12-04 12:40:10.000
268 19 3 2018-12-04 13:19:23.000
273 21 3 2018-12-04 13:28:00.000
273 19 3 2018-12-04 13:32:00.000
459 19 3 2018-12-04 15:01:04.000
What I need to achieve is:
EmployeeID EventTypeID TerminalID LoggedOn
273 19 3 2018-12-04 12:31:23.000
483 19 3 2018-12-04 12:30:10.000
268 19 3 2018-12-04 13:19:23.000
459 19 3 2018-12-04 15:01:04.000
TerminalID column value is always 3 in that scenario and it's not related with any query condition, but must be in the output for syntax requirement in the futher processing.
The bad practice to join tables using conditions in WHERE. The block WHERE need to use to filter first of all.
And aliases help to make code shorter.
SELECT * FROM
(
SELECT EmployeeID, EventTypeID, TerminalID, LoggedOn
FROM rcp..EventLogEntries
WHERE terminalid = 3
UNION
SELECT p.UserExternalIdentifier, et.ID, t.ID, el.LoggedOn
FROM viso..EventLogEntries el
JOIN viso..AccessUserPersons p ON el.PersonID = p.ID
JOIN rcp..Terminals t ON el.locationID = t.TerminalTAID
JOIN rcp..EventTypes et ON --!!! no any condition here
WHERE el.LocationID = 10
AND el.EventCode = 615
AND et.Code = 36
) results
ORDER BY LoggedOn
Try to use the following:
WITH cteData AS
(
SELECT EmployeeID, EventTypeID, TerminalID, LoggedOn
FROM rcp..EventLogEntries
WHERE terminalid = 3
UNION
SELECT p.UserExternalIdentifier, et.ID, t.ID, el.LoggedOn
FROM viso..EventLogEntries el
JOIN viso..AccessUserPersons p ON el.PersonID = p.ID
JOIN rcp..Terminals t ON el.locationID = t.TerminalTAID
JOIN rcp..EventTypes et ON --!!! no any condition here
WHERE el.LocationID = 10
AND el.EventCode = 615
AND et.Code = 36
)
SELECT q19.*
FROM
(
SELECT *
FROM cteData
WHERE EventTypeID=19
) q19
LEFT JOIN
(
SELECT *
FROM cteData
WHERE EventTypeID=21
) q21
ON q19.EmployeeID=q21.EmployeeID
WHERE (DATEDIFF(MINUTE,q19.LoggedOn,q21.LoggedOn)>4 OR q21.LoggedOn IS NULL)
If there don't need any conditions you can use CROSS JOIN.
I got your result using your data:
WITH cteData AS(
SELECT *
FROM (VALUES
(273,19,3,CAST('2018-12-04 12:31:23.000' AS datetime)),
(273,21,3,CAST('2018-12-04 12:34:18.000' AS datetime)),
(483,19,3,CAST('2018-12-04 12:40:10.000' AS datetime)),
(268,19,3,CAST('2018-12-04 13:19:23.000' AS datetime)),
(273,21,3,CAST('2018-12-04 13:28:00.000' AS datetime)),
(273,19,3,CAST('2018-12-04 13:32:00.000' AS datetime)),
(459,19,3,CAST('2018-12-04 15:01:04.000' AS datetime))
)v(EmployeeID,EventTypeID,TerminalID,LoggedOn)
)
SELECT q19.*
FROM
(
SELECT *
FROM cteData
WHERE EventTypeID=19
) q19
LEFT JOIN
(
SELECT *
FROM cteData
WHERE EventTypeID=21
) q21
ON q19.EmployeeID=q21.EmployeeID
WHERE (DATEDIFF(MINUTE,q19.LoggedOn,q21.LoggedOn)>4 OR q21.LoggedOn IS NULL)
Small change done in this part:
ON q19.EmployeeID=q21.EmployeeID AND q19.LoggedOn=dateadd(mi, 4, q21.LoggedOn)
WHERE q21.LoggedOn IS NULL

Find out average loan taken by age group in specific ranges and display them in a table

Consider the following 2 tables:
customer( **c_id**, c_name, c_dob)
customer_loan_taken( **loan_no**, c_id, taken_date, loan_amount)
How to find out average loan taken by age group 20-25, 30-35, 40-45, and display them in a single table ?
The table contents are as follows:
customer table
C_ID C_NAME C_DOB
1 Jainam Jhaveri 17-FEB-93
2 Harsh Mehra 10-DEC-91
3 Mohit Desai 15-OCT-75
4 Raj Gupta 31-AUG-80
5 Yash Shah 24-NOV-85
6 Dishank Parikh 02-OCT-78
7 Chandni Jain 06-MAR-83
8 Bhavesh Prajapati 13-MAY-71
9 Priyank Khandelwal 18-JUN-86
10 Mihir Vora 11-NOV-95
customer_loan_taken table
LOAN_NO C_ID TAKEN_DAT LOAN_AMOUNT
1011 1 12-SEP-11 100000
1012 3 20-APR-10 200010
1013 4 15-OCT-12 150000
1014 5 04-JAN-13 2500005
1015 7 15-AUG-16 2600001
1016 8 21-DEC-16 3500000
1017 9 13-NOV-17 4000000
1018 10 05-MAR-18 1010100
This is working in Oracle 12c. The trick to figure out the age can differ on database as datediff is not working in oracle. So modify it accordingly
with customer( c_id, c_name, c_dob) as
(select 1,'A','31/01/1990' from dual union
select 2,'A','31/01/1980' from dual union
select 3,'C','31/01/1970' from dual union
select 4,'D','31/08/1990' from dual),
ag as
(select c.* ,
FLOOR(TRUNC(MONTHS_BETWEEN(SYSDATE, to_date(c_dob,'DD/MM/YYYY'))) /12) as age,
case when FLOOR(TRUNC(MONTHS_BETWEEN(SYSDATE, to_date(c_dob,'DD/MM/YYYY'))) /12) between 20 and 25 then '20-25' when
FLOOR(TRUNC(MONTHS_BETWEEN(SYSDATE, to_date(c_dob,'DD/MM/YYYY'))) /12) between 30 and 35 then '30-35' when
FLOOR(TRUNC(MONTHS_BETWEEN(SYSDATE, to_date(c_dob,'DD/MM/YYYY'))) /12) between 40 and 45 then '40-45'
end as agegroup from customer c
),
customer_loan_taken( loan_no, c_id, taken_date, loan_amount)
as
(
select 101,1,'01/01/1990',1000 from dual union
select 102,2,'01/01/1990',2000 from dual union
select 103,3,'01/01/1990',3000 from dual union
select 104,4,'01/01/1990',4000 from dual
)
select distinct(ag.agegroup),avg(loan_amount) from customer_loan_taken cl,ag
where ag.c_id=cl.c_id
group by ag.agegroup
;WITH cte AS (
SELECT CASE
WHEN DATEDIFF ("YY", c_dob, GETDATE()) > 20
AND DATEDIFF ("YY", c_dob, GETDATE()) <= 25 THEN '20-25'
WHEN DATEDIFF ("YY", c_dob, GETDATE()) > 25
AND DATEDIFF ("YY", c_dob, GETDATE()) <= 30 THEN '25-30'
WHEN DATEDIFF ("YY", c_dob, GETDATE()) > 30
AND DATEDIFF ("YY", c_dob, GETDATE()) <= 35 THEN '30-35'
END AS rangedate,
l.loan_amount
FROM customer
INNER JOIN customer_loan_taken l ON customer.c_id = l.c_id
)
SELECT rangedate,
AVG(loan_amount) average
FROM cte
GROUP BY rangedate
select avg(loan_amt) "LOAN_AVG",age_range from(
select l.loan_amount as loan_amt,
(case
when FLOOR((months_between(sysdate,to_CHAR(c.c_dob,'DD-MON-YYYY')))/12)
between 20 and 25 then '20-25'
when FLOOR((months_between(sysdate,to_CHAR(c.c_dob,'DD-MON-YYYY')))/12)
between 30 and 35 then '30-35'
when FLOOR((months_between(sysdate,to_CHAR(c.c_dob,'DD-MON-YYYY')))/12)
between 40 and 45 then '40-45'
else '46-90'
end) as age_range
from customer c,cust_loan_taken l
where c.C_ID=l.C_ID) a
group by age_range;

sql - max from group flag setter

I m trying to achieve flag setting for the condition in my table below
p_id mon_year e_id flag
---- --------- ----- -----
1 2011/11 20 0
1 2011/11 21 1
1 2012/01 22 1
1 2012/02 23 0
1 2012/02 24 0
1 2012/02 25 1
2 2011/11 28 0
2 2011/11 29 1
2 2012/01 30 1
grouping by p_id,e_id and mon_year, the flag is set for the last value in the month.
I m confused how can i achieve this
I tried to achieved this by using row_number and partition to seperate out the value. By still looking for to achieved
Output by using row_number query , i have got is as below:
Grouping by
p_id mon_year e_id row
---- --------- ----- -----
1 2011/11 20 1
1 2011/11 21 2
1 2012/01 22 1
1 2012/02 23 1
1 2012/02 24 2
1 2012/02 25 3
2 2011/11 28 1
2 2011/11 29 2
2 2012/01 30 1
Max of this value would set the flag column. But i m really bugged how to achieve it. Any help would be useful.
Thanks !!
I think this is what you're going for. . . The output exactly matches your example:
declare #t table (p_id int, [year] int, [month] int, [day] int)
insert #t select 1, 2011, 11, 20
union select 1, 2011, 11, 21
union select 1, 2012, 01, 22
union select 1, 2012, 02, 23
union select 1, 2012, 02, 24
union select 1, 2012, 02, 25
union select 2, 2011, 11, 28
union select 2, 2011, 11, 29
union select 2, 2012, 01, 30
select p_id, [year], [month], [day]
, case when r=1 then 1 else 0 end flag
from
(
select p_id, [year], [month], [day]
, row_number() over (partition by p_id, [year], [month] order by [day] desc) r
from #t
) x
order by p_id, [year], [month], [day]
Output:
p_id year month day flag
1 2011 11 20 0
1 2011 11 21 1
1 2012 1 22 1
1 2012 2 23 0
1 2012 2 24 0
1 2012 2 25 1
2 2011 11 28 0
2 2011 11 29 1
2 2012 1 30 1
Try ordering by descending. In that way, you don't have to look for maximum ROW_NUMBER but when ROW_NUMBER is 1 ;)
Something like this (I didn't completely understand what you want to achieve, so this is probably not 100% accurate):
WITH r_MyTable
AS
(
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY mon_year ORDER BY p_id, e_id DESC) AS GroupRank
FROM MyTable
)
UPDATE r_MyTable
SET flag = CASE WHEN GroupRank = 1 THEN 1 ELSE 0 END;
You can use max statement on e_id to get last value for the month, code is below:
IF OBJECT_ID('tempdb..#tmptest') IS NOT NULL
DROP TABLE #tmptest
SELECT
*
INTO
#tmptest
FROM
(
SELECT '1' p_id, '2011/11' mon_year, '20' e_id, '0' flag UNION ALL
SELECT '1', '2011/11', '21', '1' UNION ALL
SELECT '1', '2012/01', '22', '1' UNION ALL
SELECT '1', '2012/02', '23', '0' UNION ALL
SELECT '1', '2012/02', '24', '0' UNION ALL
SELECT '1', '2012/02', '25', '1' UNION ALL
SELECT '2', '2011/11', '28', '0' UNION ALL
SELECT '2', '2011/11', '29', '1' UNION ALL
SELECT '2', '2012/01', '30', '1'
) as tmp
SELECT
tmptest.*
FROM
(
SELECT
MAX(e_id) e_id
,p_id
,mon_year
FROM
#tmptest
GROUP BY
p_id,mon_year
) tblLastValueEID
INNER JOIN
#tmptest tmptest
ON
tmptest.p_id = tblLastValueEID.p_id
AND
tmptest.mon_year = tblLastValueEID.mon_year
AND
tmptest.e_id = tblLastValueEID.e_id

how to update column with previous data

how to get previous record depend on unique_id and date?
i want make my table (dbo : Daily_Summary) :
ID Partner part_no Date Periode_Sum Previous_Sum
1 aa 12 2011-12-21 40
2 aa 12 2011-12-22 30 40
3 bb2 13 2011-12-22 20
4 bb2 13 2011-12-23 30 20
5 2011-12-24
6 2011-12-25
7 aa 12 2011-12-26 30 70
8 bb2 13 2011-12-27 40 50
and so on
which 'Previous_Sum' is function update, and the function only update the previous record of Periode_Sum. And group by partner, part_no and date
My display query had error to.
When i display the previous record by partner, part_no and date. the record of previous_sum only displayed the first partner.
here is my query :
SELECT ds.partner_id, ds.part_no, ds. periode_in
, ds.periode_out, ds.periode_date, ds.periode_sum,
(
SELECT F1.periode_sum
FROM Daily_Summary as F1 where
F1.periode_sum =
(
SELECT Max(F2.periode_sum)
FROM Daily_Summary as F2 where F2.periode_date < ds.periode_date
and F2.partner_id=ds.partner_id and F2.part_no = ds.part_no
)
) AS Prev_Value
FROM Daily_Summary ds
where stsrc='A'
order by ds.partner_id, ds.periode_date
i tried using declare new param but not working :
DECLARE #prev_sum INT = 0
DECLARE #dudut INT = 2
SELECT #prev_sum =
(select sum(periode_sum)
from Daily_Summary t1
where t1.partner_id = ds.partner_id and t1.part_no = ds.part_no
and t1.periode_date < ds.periode_date --and t1.id < t.id
)
FROM Daily_Summary ds
where stsrc='A'
order by ds.partner_id, ds.periode_date
select partner_id,part_no,model,periode_sum,
case when #prev_sum is null then #dudut else #prev_sum end
FROM daily_summary
where stsrc='A'
select * into #tab from (
select 1 as id, 'aa' as partner, 12 as part_no,
cast('2011-12-21' as datetime) as date, 40 as periode_sum union all
select 2, 'aa', 12, '2011-12-22', 30 union all
select 3, 'bb2', 13, '2011-12-22', 20 union all
select 4, 'bb2', 13, '2011-12-23', 30 union all
select 5, null, null, '2011-12-24', null union all
select 6, null, null, '2011-12-25', null union all
select 7, 'aa', 12, '2011-12-26', 30 union all
select 8, 'bb2', 13, '2011-12-27', 40
) t
select *, (select sum(periode_sum)
from #tab t1
where t1.partner = t.partner and t1.part_no = t.part_no
and t1.date < t.date and t1.id < t.id
) as previous_sum
from #tab t
If more than one row per day for specific pair (partner, part_no) is allowed then instead of and t1.date < t.date and t1.id < t.id you should use and t1.date <= t.date and t1.id < t.id. You can use just and t1.id < t.id if id ensures proper order (in time) for all rows.
Result:
id partner part_no date periode_sum previous_sum
1 aa 12 2011-12-21 00:00:00.000 40 NULL
2 aa 12 2011-12-22 00:00:00.000 30 40
3 bb2 13 2011-12-22 00:00:00.000 20 NULL
4 bb2 13 2011-12-23 00:00:00.000 30 20
5 NULL NULL 2011-12-24 00:00:00.000 NULL NULL
6 NULL NULL 2011-12-25 00:00:00.000 NULL NULL
7 aa 12 2011-12-26 00:00:00.000 30 70
8 bb2 13 2011-12-27 00:00:00.000 40 50