এসকিউএল সার্ভারে একটি চলমান মোট গণনা করুন


170

নিম্নলিখিত টেবিলটি কল্পনা করুন (ডাকা TestTable):

id     somedate    somevalue
--     --------    ---------
45     01/Jan/09   3
23     08/Jan/09   5
12     02/Feb/09   0
77     14/Feb/09   7
39     20/Feb/09   34
33     02/Mar/09   6

আমি এমন একটি কোয়েরি চাই যা তারিখের ক্রমানুসারে চলমান মোট ফেরত দেয়, যেমন:

id     somedate    somevalue  runningtotal
--     --------    ---------  ------------
45     01/Jan/09   3          3
23     08/Jan/09   5          8
12     02/Feb/09   0          8
77     14/Feb/09   7          15  
39     20/Feb/09   34         49
33     02/Mar/09   6          55

আমি জানি এসকিউএল সার্ভার 2000/2005/2008 এ করার বিভিন্ন উপায় রয়েছে

আমি এই ধরণের পদ্ধতিতে বিশেষভাবে আগ্রহী যা সমষ্টি-সেট-বিবৃতি কৌশল ব্যবহার করে:

INSERT INTO @AnotherTbl(id, somedate, somevalue, runningtotal) 
   SELECT id, somedate, somevalue, null
   FROM TestTable
   ORDER BY somedate

DECLARE @RunningTotal int
SET @RunningTotal = 0

UPDATE @AnotherTbl
SET @RunningTotal = runningtotal = @RunningTotal + somevalue
FROM @AnotherTbl

... এটি খুব দক্ষ তবে আমি শুনেছি এর চারপাশে সমস্যা রয়েছে কারণ আপনি অবশ্যই গ্যারান্টি দিতে পারবেন না যে UPDATEবিবৃতিটি সঠিক ক্রমে সারিগুলি প্রসেস করবে। সম্ভবত আমরা এই সমস্যা সম্পর্কে কিছু সুনির্দিষ্ট উত্তর পেতে পারি।

কিন্তু সম্ভবত অন্যান্য উপায় আছে যা লোকেরা পরামর্শ দিতে পারে?

সম্পাদনা করুন: এখন উপরোক্ত সেটআপ এবং 'আপডেট ট্রিক' উদাহরণ সহ একটি স্ক্যলফিডাল


ব্লগস.এমএসএন / এসকিলিটিপস / অর্চিভ / ২০০৫ / 7 / ২০ / 44০১০৩৩.aspx আপনার আপডেটের মাধ্যমে একটি অর্ডার যুক্ত করুন ... সেট করুন এবং আপনি গ্যারান্টি পাবেন।
সাইমন ডি

তবে অর্ডার কোনও আপডেটের বিবৃতিতে প্রয়োগ করা যাবে না ... তা কি সম্ভব?
কোডুলিকে

এছাড়াও sqlperformance.com/2012/07/t-sql-queries/running-totals দেখুন বিশেষত যদি আপনি এসকিউএল সার্ভার 2012 ব্যবহার করে থাকেন
অ্যারন বারট্রান্ড

উত্তর:


133

আপডেট , আপনি যদি এসকিউএল সার্ভার 2012 চালাচ্ছেন তবে দেখুন: https://stackoverflow.com/a/10309947 47

সমস্যাটি হ'ল ওভার ক্লজটির এসকিউএল সার্ভার বাস্তবায়ন কিছুটা সীমাবদ্ধ

ওরাকল (এবং এএনএসআই-এসকিউএল) আপনাকে এ জাতীয় কাজ করতে দেয়:

 SELECT somedate, somevalue,
  SUM(somevalue) OVER(ORDER BY somedate 
     ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) 
          AS RunningTotal
  FROM Table

এসকিউএল সার্ভার আপনাকে এই সমস্যার কোনও পরিষ্কার সমাধান দেয় না। আমার অন্ত্রে আমাকে বলছে যে এটি সেই বিরল ক্ষেত্রে একটি যেখানে একটি কার্সার দ্রুততম, যদিও আমাকে বড় ফলাফলগুলির জন্য কিছু বেঞ্চমার্কিং করতে হবে।

আপডেট ট্রিকটি সুবিধাজনক তবে আমি এর মোটামুটি ভঙ্গুর অনুভব করছি। দেখে মনে হচ্ছে আপনি যদি একটি পূর্ণ টেবিল আপডেট করে থাকেন তবে তা প্রাথমিক কী অনুসারে অগ্রসর হবে। সুতরাং আপনি যদি একটি অগ্রণী কী হিসাবে আরোহণের জন্য আপনার তারিখটি সেট করেন তবে আপনি probablyনিরাপদে থাকবেন। তবে আপনি একটি অনিবন্ধিত এসকিউএল সার্ভার বাস্তবায়ন বিশদের উপর নির্ভর করছেন (কোয়েরিটি যদি দুটি প্রোক দ্বারা সম্পাদিত হয় তবে আমি ভাবছি কী হবে, দেখুন: ম্যাক্সডপ):

সম্পূর্ণ কাজের নমুনা:

drop table #t 
create table #t ( ord int primary key, total int, running_total int)

insert #t(ord,total)  values (2,20)
-- notice the malicious re-ordering 
insert #t(ord,total) values (1,10)
insert #t(ord,total)  values (3,10)
insert #t(ord,total)  values (4,1)

declare @total int 
set @total = 0
update #t set running_total = @total, @total = @total + total 

select * from #t
order by ord 

ord         total       running_total
----------- ----------- -------------
1           10          10
2           20          30
3           10          40
4           1           41

আপনি একটি মানদণ্ডের জন্য জিজ্ঞাসা করেছেন এটি নিম্ন ডাউন।

এটির দ্রুততম নিরাপদ উপায়টি কার্সার হবে, এটি ক্রস-জয়েনের সম্পর্কিত সম্পর্কিত সাব-কোয়ের চেয়ে দ্রুততার একটি ক্রম।

পরম দ্রুততম উপায় হল আপডেটের কৌশল। এর সাথে আমার একমাত্র উদ্বেগ হ'ল আমি নিশ্চিত নই যে সব পরিস্থিতিতে আপডেটটি লিনিয়ার পথে এগিয়ে যাবে will ক্যোয়ারিতে এমন কোনও কিছুই নেই যা স্পষ্টভাবে তাই বলে।

নীচের লাইন, প্রোডাকশন কোডের জন্য আমি কার্সারের সাথে যাব।

পরীক্ষার ডেটা:

create table #t ( ord int primary key, total int, running_total int)

set nocount on 
declare @i int
set @i = 0 
begin tran
while @i < 10000
begin
   insert #t (ord, total) values (@i,  rand() * 100) 
    set @i = @i +1
end
commit

পরীক্ষা 1:

SELECT ord,total, 
    (SELECT SUM(total) 
        FROM #t b 
        WHERE b.ord <= a.ord) AS b 
FROM #t a

-- CPU 11731, Reads 154934, Duration 11135 

পরীক্ষা 2:

SELECT a.ord, a.total, SUM(b.total) AS RunningTotal 
FROM #t a CROSS JOIN #t b 
WHERE (b.ord <= a.ord) 
GROUP BY a.ord,a.total 
ORDER BY a.ord

-- CPU 16053, Reads 154935, Duration 4647

পরীক্ষা 3:

DECLARE @TotalTable table(ord int primary key, total int, running_total int)

DECLARE forward_cursor CURSOR FAST_FORWARD 
FOR 
SELECT ord, total
FROM #t 
ORDER BY ord


OPEN forward_cursor 

DECLARE @running_total int, 
    @ord int, 
    @total int
SET @running_total = 0

FETCH NEXT FROM forward_cursor INTO @ord, @total 
WHILE (@@FETCH_STATUS = 0)
BEGIN
     SET @running_total = @running_total + @total
     INSERT @TotalTable VALUES(@ord, @total, @running_total)
     FETCH NEXT FROM forward_cursor INTO @ord, @total 
END

CLOSE forward_cursor
DEALLOCATE forward_cursor

SELECT * FROM @TotalTable

-- CPU 359, Reads 30392, Duration 496

পরীক্ষা 4:

declare @total int 
set @total = 0
update #t set running_total = @total, @total = @total + total 

select * from #t

-- CPU 0, Reads 58, Duration 139

1
ধন্যবাদ। সুতরাং আপনার কোডের নমুনাটি প্রদর্শন করাতে হবে যে এটি প্রাথমিক কী অনুসারে যোগ হবে। এটি জেনে রাখা আকর্ষণীয় হবে যে বৃহত্তর ডেটা সেটে যোগ দেওয়ার চেয়ে কার্সারগুলি এখনও আরও দক্ষ।
কোডুলিকে

1
আমি কেবল সিটিই @ মার্টিন পরীক্ষা করেছি, আপডেট ট্রিকের কাছাকাছি কিছুই আসে না - কার্সার পড়লে কম মনে হয়। এখানে একটি প্রোফাইলার ট্রেস i.stack.imgur.com/BbZq3.png
স্যাম জাফরান

3
@ মার্টিন ডেনালি এই এমএসডিএন.মাইক্রোসফটকম /en-us/library/ms189461(v=SQL.110).aspx
স্যাম

1
এই উত্তরে দেওয়া সমস্ত কাজের জন্য +1 - আমি আপডেট আপডেট পছন্দ করি; একটি পার্টিশন এই আপডেটের স্ক্রিপ্ট মধ্যে নির্মিত যেতে পারে? উদাহরণস্বরূপ, যদি কোনও অতিরিক্ত ক্ষেত্র "গাড়ী রঙ" থাকে তবে এই স্ক্রিপ্টটি প্রতিটি "গাড়ির রঙ" পার্টিশনের মধ্যে মোট চলমান ফিরে আসতে পারে?
কেন

2
প্রাথমিক (ওরাকল (এবং এএনএসআই-এসকিউএল)) উত্তরটি এখন এসকিউএল সার্ভারে কাজ করে 2017. আপনাকে ধন্যবাদ, খুব মার্জিত!
দানিদেব


40

যদিও স্যাম জাফরন এতে দুর্দান্ত কাজ করেছে, তবুও তিনি এই সমস্যার জন্য পুনরাবৃত্ত সাধারণ টেবিল এক্সপ্রেশন কোড সরবরাহ করেন নি। এবং আমাদের জন্য যারা এসকিউএল সার্ভার ২০০৮ আর 2 এর সাথে কাজ করছেন এবং ডেনালি নয়, এটি এখনও মোট রান করার দ্রুততম উপায়, এটি আমার ওয়ার্ক কম্পিউটারে 100000 সারি জন্য কার্সারের চেয়ে প্রায় 10 গুণ বেশি দ্রুত এবং এটি ইনলাইন অনুসন্ধানও রয়েছে query
সুতরাং, এটি এখানে রয়েছে (আমি মনে করি যে ordটেবিলের একটি কলাম রয়েছে এবং এটি ফাঁক ছাড়াই ক্রমিক সংখ্যা, দ্রুত প্রক্রিয়াকরণের জন্য এই সংখ্যার উপরও অনন্য বাধা থাকতে হবে):

;with 
CTE_RunningTotal
as
(
    select T.ord, T.total, T.total as running_total
    from #t as T
    where T.ord = 0
    union all
    select T.ord, T.total, T.total + C.running_total as running_total
    from CTE_RunningTotal as C
        inner join #t as T on T.ord = C.ord + 1
)
select C.ord, C.total, C.running_total
from CTE_RunningTotal as C
option (maxrecursion 0)

-- CPU 140, Reads 110014, Duration 132

sql fiddle demo

আপডেট আমি এই সম্পর্কে জানতে আগ্রহী ছিল পরিবর্তনশীল সঙ্গে আপডেট বা করা বিচিত্র আপডেট । সুতরাং সাধারণত এটি ঠিক কাজ করে তবে আমরা কীভাবে নিশ্চিত হতে পারি যে এটি প্রতিবার কাজ করে? ভাল, এখানে একটি সামান্য কৌশল (এটি এখানে খুঁজে পেয়েছে - এটি এখানে খুঁজে পেয়েছেন - http://www.sqlservercentral.com/forums/Topic802558-203-21.aspx#bm981258 ) - আপনি কেবল বর্তমান এবং পূর্ববর্তী পরীক্ষা করে দেখুন এবং সেগুলি থেকে পৃথক হওয়ার ক্ষেত্রে অ্যাসাইনমেন্টটি ordব্যবহার করুন 1/0you আপনি প্রত্যাশা করছেন:

declare @total int, @ord int

select @total = 0, @ord = -1

update #t set
    @total = @total + total,
    @ord = case when ord <> @ord + 1 then 1/0 else ord end,
    ------------------------
    running_total = @total

select * from #t

-- CPU 0, Reads 58, Duration 139

আপনার টেবিলে আপনার কাছে সঠিক ক্লাস্টারড ইনডেক্স / প্রাইমারি কী থাকলে যা দেখেছি তা থেকে (আমাদের ক্ষেত্রে এটি সূচক ord_idহবে) আপডেট সর্বদা লিনিয়ার উপায়ে এগিয়ে চলবে (কখনই শূন্য দ্বারা বিভাজনের মুখোমুখি হয়নি)। এটি বলেছিল, আপনি এটি প্রোডাকশন কোডে ব্যবহার করতে চান কিনা তা সিদ্ধান্ত নিতে হবে আপনারা :)

আপডেট 2 আমি এই উত্তরটির সাথে লিঙ্ক করছি, কারণ এটিতে অদ্ভুত আপডেটের অবিশ্বস্ততা সম্পর্কে কিছু দরকারী তথ্য রয়েছে - এনভারচার কনটেনটেশন / ইনডেক্স / এনভারচার (সর্বাধিক) অনির্বচনীয় আচরণ


6
এই উত্তরটি আরও স্বীকৃতি প্রাপ্য (অথবা এটিতে কিছু ত্রুটি রয়েছে যা আমি দেখতে পাচ্ছি না?)
ব্যবহারকারী 1068352

একটি ক্রমিক সংখ্যা থাকা উচিত যাতে আপনি অর্ড = অর্ড + 1 এ যোগ দিতে পারেন এবং কখনও কখনও এর জন্য আরও কিছুটা কাজের প্রয়োজন হয়। তবে যাইহোক, এসকিউএল ২০০৮ আর 2 এ আমি এই সমাধানটি ব্যবহার করছি
রোমান পেকার

SQLServer2008R2 এ +1 আমি পুনরাবৃত্ত সিটিই সহ পদ্ধতির পছন্দও করি। এফওয়াইআই, টেবিলগুলির জন্য মানটি সন্ধান করার জন্য, যে ফাঁকগুলিকে আমি একটি সম্পর্কিত সাব-কোয়েরি ব্যবহার করি allow এটি কোয়েরিতে
আলেকসান্ডার

2
আপনার ডেটাটির জন্য ইতিমধ্যে যেখানে আপনার কাছে অর্ডিনাল রয়েছে এবং আপনি এসকিউএল ২০০৮ আর 2 এর উপর ভিত্তি করে সংক্ষিপ্ত (নন কার্সার) সেট সমাধান সন্ধান করছেন, এটি নিখুঁত বলে মনে হয়।
নিক.এমসিডার্মাইড

1
প্রতিটি চলমান মোট ক্যোয়ারিতে একটি নিয়মিত ক্ষেত্র থাকবে না যা সামঞ্জস্যপূর্ণ। কখনও কখনও একটি ডেটটাইম ফিল্ড আপনার যা থাকে তা বা রেকর্ডগুলি সাজানোর মাঝখানে থেকে মুছে ফেলা হয়। এ কারণেই এটি প্রায়শই ব্যবহার হয় না।
রবিবেন

28

এসকিউএল 2005 এ অ্যাপ্লিকেশন অপারেটর এবং এর জন্য উচ্চতর কাজ করে:

select
    t.id ,
    t.somedate ,
    t.somevalue ,
    rt.runningTotal
from TestTable t
 cross apply (select sum(somevalue) as runningTotal
                from TestTable
                where somedate <= t.somedate
            ) as rt
order by t.somedate

5
ছোট ডেটাসেটের জন্য খুব ভাল কাজ করে। একটি খারাপ দিকটি হ'ল আপনার একইরকম থাকতে হবে যেখানে অভ্যন্তরীণ এবং বাহ্যিক কোয়েরিতে ক্লজ রয়েছে।
সায়ার

যেহেতু আমার কয়েকটি তারিখ হুবহু একই ছিল (এক সেকেন্ডের ভগ্নাংশের নিচে) আমাকে যুক্ত করতে হয়েছিল: সারি_নম্বার () ওভার (txndate দ্বারা অর্ডার) এর অভ্যন্তরীণ এবং বাইরের টেবিলে এবং এটি চালানোর জন্য কয়েকটি যৌগিক সূচক। স্লিক / সহজ সমাধান। বিটিডাব্লু, পরীক্ষিত ক্রস সাবকোয়ারির বিরুদ্ধে প্রয়োগ করুন ... এটি কিছুটা দ্রুত।
pgcpa

এটি খুব পরিষ্কার এবং ছোট ডেটা সেটগুলির সাথে ভাল কাজ করে; রিকার্সিভ সিটিই

এটিও দুর্দান্ত সমাধান (ছোট ডেটা সেটগুলির জন্য), তবে আপনাকে সচেতন হতে হবে যে এটি কোনও কোনও সময়ের কলামটি অনন্য হতে বোঝায়
রোমান পেকার

11
SELECT TOP 25   amount, 
    (SELECT SUM(amount) 
    FROM time_detail b 
    WHERE b.time_detail_id <= a.time_detail_id) AS Total FROM time_detail a

আপনি অভ্যন্তরীণ নির্বাচনী স্টেটমেন্টের তুলনায় তুলনা করতে স্বেচ্ছাসেবক কলাম তৈরি করতে ROW_NUMBER () ফাংশন এবং একটি টেম্প টেবিলও ব্যবহার করতে পারেন।


1
এটি সত্যিই অদক্ষ ... তবে তারপরে আবার স্কিল সার্ভারে এটি করার কোনও সত্যিকারের পরিষ্কার উপায় নেই
স্যাম সাফ্রন

অবশ্যই এটি অদক্ষ - তবে এটি কাজটি করে এবং সঠিক বা ভুল ক্রমে মৃত্যুদন্ড কার্যকর করার জন্য কোনও প্রশ্নই আসে না।
স্যাম অ্যাক্স

ধন্যবাদ, বিকল্প উত্তর পেতে এটি কার্যকর এবং দক্ষ সমালোচনা করতেও দরকারী
কোডুলাইক

7

একটি সহযোগিত সাব-কোয়েরি ব্যবহার করুন। খুব সহজ, আপনি এখানে যান:

SELECT 
somedate, 
(SELECT SUM(somevalue) FROM TestTable t2 WHERE t2.somedate<=t1.somedate) AS running_total
FROM TestTable t1
GROUP BY somedate
ORDER BY somedate

কোডটি ঠিক সঠিক নাও হতে পারে তবে আমি নিশ্চিত যে ধারণাটি।

গ্রুপ কর্তৃক তারিখটি একাধিকবার প্রদর্শিত হওয়ার পরে, আপনি কেবল ফলাফলের সেটে একবার এটি দেখতে চাইবেন।

যদি আপনি পুনরাবৃত্তি তারিখগুলি দেখতে আপত্তি না করেন বা আপনি মূল মান এবং আইডি দেখতে চান তবে নীচের বিষয়গুলি যা আপনি চান:

SELECT 
id,
somedate, 
somevalue,
(SELECT SUM(somevalue) FROM TestTable t2 WHERE t2.somedate<=t1.somedate) AS running_total
FROM TestTable t1
ORDER BY somedate

ধন্যবাদ ... সহজ ছিল দুর্দান্ত। পারফরম্যান্স যুক্ত করার জন্য একটি সূচক ছিল, তবে এটি যথেষ্ট সহজ ছিল (ডাটাবেস ইঞ্জিন টিউনিং উপদেষ্টার কাছ থেকে একটি প্রস্তাবনা নিয়েছিল), এবং তারপরে এটি শটের মতো চলে।
ডগ_ইভিসন

5

আপনি অস্বীকার করতেও পারেন - একই টেবিলটিতে চলমান মোট সঞ্চয় করুন:

http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/23/denormalizing-to-enforce-business-rules-running-totals.aspx

অন্য যে কোনও সমাধানের চেয়ে অনেক দ্রুত কাজ নির্বাচন করে তবে পরিবর্তনগুলি ধীর হতে পারে


4

ধরে নিই যে উইন্ডোটিংটি এসকিউএল সার্ভার ২০০৮-তে যেমন এটি অন্য কোথাও চলেছে (যে আমি চেষ্টা করেছি) এর মতো কাজ করে, এটিকে একবার দেখুন:

select testtable.*, sum(somevalue) over(order by somedate)
from testtable
order by somedate;

দুটিই MSDN বলছে এটি এসকিউএল সার্ভার ২০০৮-এ (এবং সম্ভবত ২০০ 2005-এও পাওয়া যায়) তবে এটি ব্যবহার করার মতো কোনও উদাহরণ আমার কাছে নেই।

সম্পাদনা করুন: ভাল, স্পষ্টতই এসকিউএল সার্ভার একটি "উইন্ডো স্পেসিফিকেশন" ("ওভার (...)") "পার্টিশন বাই" নির্দিষ্ট করে না দিয়ে (ফলাফলকে গ্রুপে ভাগ করে নিলেও গ্রুপ যেভাবে গ্রুপ করে সেভাবে একত্রিত না করে) অনুমতি দেয় না। বিরক্তিকর - এমএসডিএন সিনট্যাক্স রেফারেন্সটি পরামর্শ দেয় যে এটির optionচ্ছিক, তবে আমার কাছে এই মুহুর্তে কেবলমাত্র এসকিএলসার্ভার 2000 উদাহরণ রয়েছে।

আমি যে ক্যোয়ারী দিয়েছি তা ওরাকল 10.2.0.3.0 এবং পোস্টগ্রিসকিউএল 8.4-বিটা উভয় ক্ষেত্রেই কাজ করে। সুতরাং এমএসকে ধরতে বলুন;)


2
SUM এর সাথে ওভার ব্যবহার করা এই ক্ষেত্রে চলমান মোট দিতে কার্যকর হবে না। ওভার ক্লজটি সুমের সাথে ব্যবহার করার সময় অর্ডার গ্রহণ করে না। আপনাকে বাই পার্টিশন ব্যবহার করতে হবে, যা মোট চলতে চলবে না।
স্যাম অ্যাক্স

ধন্যবাদ, কেন এটি অকার্যকর হয় তা শুনতে এটি আসলে কার্যকর। আরাকনিদ সম্ভবত আপনি নিজের উত্তরটি সম্পাদনা করতে পারেন কেন এটি বিকল্প নয় তা ব্যাখ্যা করার জন্য
কোডুলাইক


এটি আসলে আমার পক্ষে কাজ করে, কারণ আমার বিভাজন দরকার - সুতরাং এটি সর্বাধিক জনপ্রিয় উত্তর না হলেও এটি এসকিউএল-এর আরটি-র জন্য আমার সমস্যার সহজ সমাধান।
উইলিয়াম এমবি

আমার সাথে এমএসএসকিউএল ২০০৮ নেই, তবে আমি মনে করি আপনি সম্ভবত পার্টিশন করতে পারতেন (নাল নির্বাচন করুন) এবং পার্টিশন সমস্যাটি ঘিরে ফেলবেন। বা তার সাথে একটি সাবলেট 1 partitionmeএবং এটি দ্বারা বিভাজন করুন। এছাড়াও, রিপোর্ট করার সময় সম্ভবত বাস্তব জীবনের পরিস্থিতিতে সম্ভবত বিভাজন প্রয়োজন।
নুরেটিন

4

আপনি উপরে SQL সার্ভার 2008 আর 2 ব্যবহার করছেন। তারপরে, এটি করা সবচেয়ে স্বল্পতম উপায় হবে;

Select id
    ,somedate
    ,somevalue,
LAG(runningtotal) OVER (ORDER BY somedate) + somevalue AS runningtotal
From TestTable 

বিলম্বপূর্ববর্তী সারির মান পেতে ব্যবহার করা হয়। আপনি আরও তথ্যের জন্য গুগল করতে পারেন।

[1]:


1
আমি বিশ্বাস করি যে LAG কেবলমাত্র এসকিউএল সার্ভারে রয়েছে 2012 এবং
তারপরে

1
ল্যাগ () ব্যবহার করা উন্নত হয় না SUM(somevalue) OVER(...) যার উপর আমার কাছে অনেকটা ক্লিনার মনে হয়
Used_By_Already

2

আমি বিশ্বাস করি যে নীচে সাধারণ অন্তর্ভুক্ত যোগ অপারেশন ব্যবহার করে একটি চলমান মোট অর্জন করা সম্ভব।

SELECT
     ROW_NUMBER() OVER (ORDER BY SomeDate) AS OrderID
    ,rt.*
INTO
    #tmp
FROM
    (
        SELECT 45 AS ID, CAST('01-01-2009' AS DATETIME) AS SomeDate, 3 AS SomeValue
        UNION ALL
        SELECT 23, CAST('01-08-2009' AS DATETIME), 5
        UNION ALL
        SELECT 12, CAST('02-02-2009' AS DATETIME), 0
        UNION ALL
        SELECT 77, CAST('02-14-2009' AS DATETIME), 7
        UNION ALL
        SELECT 39, CAST('02-20-2009' AS DATETIME), 34
        UNION ALL
        SELECT 33, CAST('03-02-2009' AS DATETIME), 6
    ) rt

SELECT
     t1.ID
    ,t1.SomeDate
    ,t1.SomeValue
    ,SUM(t2.SomeValue) AS RunningTotal
FROM
    #tmp t1
    JOIN #tmp t2
        ON t2.OrderID <= t1.OrderID
GROUP BY
     t1.OrderID
    ,t1.ID
    ,t1.SomeDate
    ,t1.SomeValue
ORDER BY
    t1.OrderID

DROP TABLE #tmp

হ্যাঁ, আমি মনে করি এটি স্যাম জাফরনের উত্তরে 'টেস্ট 3' এর সমান।
কোডুলিকে

2

নিম্নলিখিত প্রয়োজনীয় ফলাফল উত্পাদন করবে।

SELECT a.SomeDate,
       a.SomeValue,
       SUM(b.SomeValue) AS RunningTotal
FROM TestTable a
CROSS JOIN TestTable b
WHERE (b.SomeDate <= a.SomeDate) 
GROUP BY a.SomeDate,a.SomeValue
ORDER BY a.SomeDate,a.SomeValue

সোমডেটে একটি ক্লাস্টারড ইনডেক্স থাকা কার্যকারিতাটি ব্যাপকভাবে উন্নতি করবে।


@ ডেভ আমি মনে করি যে এই প্রশ্নটি করার একটি কার্যকর উপায় সন্ধান করার চেষ্টা করছে, বড় সেটগুলির জন্য ক্রস জয়েনিং সত্যিই ধীর হতে চলেছে
স্যাম সাফরন

ধন্যবাদ, বিকল্প উত্তর পেতে এটি কার্যকর এবং দক্ষ সমালোচনা করতেও দরকারী
কোডুলাইক

2

যোগদান ব্যবহার করে আরেকটি প্রকরণ হ'ল যোগদান ব্যবহার করা। এখন ক্যোয়ারীটি এমন দেখাচ্ছে:

    SELECT a.id, a.value, SUM(b.Value)FROM   RunTotalTestData a,
    RunTotalTestData b
    WHERE b.id <= a.id
    GROUP BY a.id, a.value 
    ORDER BY a.id;

আরো জন্য আপনি এই লিঙ্কটি visite করতে http://askme.indianyouth.info/details/calculating-simple-running-totals-in-sql-server-12


2

যদিও এটি করার সর্বোত্তম উপায়টি উইন্ডো ফাংশনটি ব্যবহার করা হবে, তবে এটি একটি সাধারণ সম্পর্কিত সম্পর্কিত সাব-কোয়েরি ব্যবহার করেও করা যেতে পারে ।

Select id, someday, somevalue, (select sum(somevalue) 
                                from testtable as t2
                                where t2.id = t1.id
                                and t2.someday <= t1.someday) as runningtotal
from testtable as t1
order by id,someday;

0
BEGIN TRAN
CREATE TABLE #Table (_Id INT IDENTITY(1,1) ,id INT ,    somedate VARCHAR(100) , somevalue INT)


INSERT INTO #Table ( id  ,    somedate  , somevalue  )
SELECT 45 , '01/Jan/09', 3 UNION ALL
SELECT 23 , '08/Jan/09', 5 UNION ALL
SELECT 12 , '02/Feb/09', 0 UNION ALL
SELECT 77 , '14/Feb/09', 7 UNION ALL
SELECT 39 , '20/Feb/09', 34 UNION ALL
SELECT 33 , '02/Mar/09', 6 

;WITH CTE ( _Id, id  ,  _somedate  , _somevalue ,_totvalue ) AS
(

 SELECT _Id , id  ,    somedate  , somevalue ,somevalue
 FROM #Table WHERE _id = 1
 UNION ALL
 SELECT #Table._Id , #Table.id  , somedate  , somevalue , somevalue + _totvalue
 FROM #Table,CTE 
 WHERE #Table._id > 1 AND CTE._Id = ( #Table._id-1 )
)

SELECT * FROM CTE

ROLLBACK TRAN

আপনি এখানে কী করছেন সে সম্পর্কে আপনার সম্ভবত কিছু তথ্য দেওয়া উচিত এবং এই বিশেষ পদ্ধতির কোনও সুবিধা / অসুবিধাগুলি নোট করুন।
টিটি।

0

চলমান মোট গণনা করার 2 টি সহজ উপায় এখানে:

পদ্ধতির 1 : আপনার ডিবিএমএস যদি বিশ্লেষণমূলক কার্যগুলি সমর্থন করে তবে এটি এইভাবেই লেখা যেতে পারে

SELECT     id
           ,somedate
           ,somevalue
           ,runningtotal = SUM(somevalue) OVER (ORDER BY somedate ASC)
FROM       TestTable

পদ্ধতির 2 : যদি আপনার ডাটাবেস সংস্করণ / ডিবিএমএস নিজেই বিশ্লেষণাত্মক কার্যগুলি সমর্থন না করে তবে আপনি আউটর অ্যাপ্লিকেশন ব্যবহার করতে পারবেন

SELECT     T.id
           ,T.somedate
           ,T.somevalue
           ,runningtotal = OA.runningtotal
FROM       TestTable T
           OUTER APPLY (
                           SELECT   runningtotal = SUM(TI.somevalue)
                           FROM     TestTable TI
                           WHERE    TI.somedate <= S.somedate
                       ) OA;

দ্রষ্টব্য: - আলাদা আলাদা পার্টিশনের জন্য যদি আপনার চলমান মোট গণনা করতে হয় তবে তা এখানে পোস্ট করা হিসাবে করা যেতে পারে: সারিগুলিতে চলমান মোট গণনা এবং আইডি দ্বারা গোষ্ঠীকরণ

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.