पिछली और वास्तविक पंक्ति मानों के आधार पर पंक्ति मान की गणना करें


9

हाय सब लोग और आपकी मदद के लिए धन्यवाद।
मेरे पास निम्न स्थिति है: एक तालिका जिसे स्टेटमेंट्स कहा जाता है जिसमें फ़ील्ड आईडी (int), stmnt_date (दिनांक), डेबिट (डबल), क्रेडिट (डबल) और बैलेंस (डबल) शामिल हैं मेरी मेज की संरचना

मैं इन नियमों का पालन करते हुए शेष राशि की गणना करना चाहता हूं:

पहली पंक्ति का संतुलन ( कालानुक्रमिक ) = डेबिट - क्रेडिट और बाकी पंक्तियों के लिए

वर्तमान पंक्ति संतुलन = कालानुक्रमिक रूप से पिछली पंक्ति शेष + वर्तमान पंक्ति डेबिट - वर्तमान पंक्ति क्रेडिट

जैसा कि आप देख सकते हैं कि पंक्तियों के ऊपर की तस्वीर तारीख से व्यवस्थित नहीं है और इसलिए मैंने stmnt_date मान के महत्व पर जोर देने के लिए कालानुक्रमिक शब्द का दो बार उपयोग किया है।

आपकी मदद के लिए बहुत बहुत शुक्रिया।


क्या आप डेबिट और क्रेडिट क्षेत्रों को एक क्षेत्र में शामिल करने में सक्षम हैं? यदि ऐसा है, तो आप ऋण के रूप में नकारात्मक मूल्यों और सकारात्मक मूल्यों का उपयोग कर सकते हैं।
माइक

1
भविष्य के प्रश्नों के लिए (क्योंकि इसका उत्तर दिया गया है), पाठ में पोस्ट कोड, प्रिंट-स्क्रीन नहीं। इसमें CREATE TABLEस्टेटमेंट और सैंपल डेटा (साथ INSERT) भी शामिल हैं।
ypercube y

आपके उत्तर @ypercube के लिए श्रद्धांजलि में, इसे पढ़ने वाले किसी भी व्यक्ति के लिए मैंने dba.stackexchange.com/a/183207/131900
Zack Morris

जवाबों:


8

यह मानते हुए कि stmnt_dateएक है UNIQUEबाधा, इस विंडो / विश्लेषणात्मक कार्यों के साथ काफी आसान होगा:

SELECT 
    s.stmnt_date, s.debit, s.credit,
    SUM(s.debit - s.credit) OVER (ORDER BY s.stmnt_date
                                  ROWS BETWEEN UNBOUNDED PRECEDING
                                           AND CURRENT ROW)
        AS balance
FROM
    statements AS s
ORDER BY
    stmnt_date ;

दुर्भाग्य से, MySQL ने विश्लेषणात्मक कार्यों को लागू नहीं किया है (अभी तक)। आप समस्या को या तो सख्त SQL के साथ हल कर सकते हैं, तालिका को स्वयं जोड़कर (जो कि 100% काम करने के बजाय अक्षम होना चाहिए) या एक विशिष्ट MySQL सुविधा का उपयोग करके, चर (जो काफी कुशल होगा लेकिन आपको इसका परीक्षण करना होगा mysql को अपग्रेड करते समय, यह सुनिश्चित करने के लिए कि परिणाम अभी भी सही हैं और कुछ अनुकूलन में सुधार नहीं किया गया है):

SELECT 
    s.stmnt_date, s.debit, s.credit,
    @b := @b + s.debit - s.credit AS balance
FROM
    (SELECT @b := 0.0) AS dummy 
  CROSS JOIN
    statements AS s
ORDER BY
    stmnt_date ;

आपके डेटा के साथ, इसका परिणाम होगा:

+------------+-------+--------+---------+
| stmnt_date | debit | credit | balance |
+------------+-------+--------+---------+
| 2014-05-15 |  3000 |      0 |    3000 |
| 2014-06-17 | 20000 |      0 |   23000 |
| 2014-07-16 |     0 |   3000 |   20000 |
| 2014-08-14 |     0 |   3000 |   17000 |
| 2015-02-01 |  3000 |      0 |   20000 |
+------------+-------+--------+---------+
5 rows in set (0.00 sec)

6

मुझे लगता है कि आप निम्नलिखित कोशिश कर सकते हैं:

set @balance := 0;

SELECT stmnt_date, debit, credit, (@balance := @balance + (debit - credit)) as Balance
FROM statements
ORDER BY stmnt_date;

2

ypercube का उत्तर बहुत शानदार है (मैंने कभी भी डमी के माध्यम से एक एकल क्वेरी के भीतर एक वैरिएबल निर्माण नहीं देखा था), इसलिए यहां आपकी सुविधा के लिए CREATE TABLE स्टेटमेंट है।

Google छवि खोज में सारणीबद्ध डेटा छवियों के लिए, आप इसे टेक्स्ट दस्तावेज़ में परिवर्तित करने के लिए https://convertio.co/ocr/ या https://ocr.space/ का उपयोग कर सकते हैं । यदि OCR स्तंभों का ठीक से पता नहीं लगाता है, और आपके पास एक Mac है, तो आयताकार चयन करने के लिए नीचे दिए गए विकल्प कुंजी के साथ TextWrangler का उपयोग करें और स्तंभों को चारों ओर ले जाएं। एसक्यूएल प्रो , टेक्स्टवर्ंगलर जैसे एसक्यूएल एडिटर का संयोजन और Google डॉक्स की तरह एक स्प्रेडशीट, टैब से अलग किए गए सारणीबद्ध डेटा से निपटने में बेहद कुशल है।

अगर मैं यह सब एक टिप्पणी में डाल सकता हूं, तो कृपया इस उत्तर को न दें।

-- DROP TABLE statements;

CREATE TABLE IF NOT EXISTS statements (
  id integer NOT NULL AUTO_INCREMENT,
  stmnt_date date,
  debit integer not null default 0,
  credit integer not null default 0,
  PRIMARY KEY (id)
);

INSERT INTO statements
(stmnt_date  , debit, credit) VALUES
('2014-06-17', 20000, 0     ),
('2014-08-14', 0    , 3000  ),
('2014-07-16', 0    , 3000  ),
('2015-02-01', 3000 , 0     ),
('2014-05-15', 3000 , 0     );

-- this is slightly modified from ypercube's (@b := 0 vs @b := 0.0)
SELECT 
    s.stmnt_date, s.debit, s.credit,
    @b := @b + s.debit - s.credit AS balance
FROM
    (SELECT @b := 0) AS dummy 
CROSS JOIN
    statements AS s
ORDER BY
    stmnt_date ASC;

/* result
+------------+-------+--------+---------+
| stmnt_date | debit | credit | balance |
+------------+-------+--------+---------+
| 2014-05-15 |  3000 |      0 |    3000 |
| 2014-06-17 | 20000 |      0 |   23000 |
| 2014-07-16 |     0 |   3000 |   20000 |
| 2014-08-14 |     0 |   3000 |   17000 |
| 2015-02-01 |  3000 |      0 |   20000 |
+------------+-------+--------+---------+
5 rows in set (0.00 sec)
*/

1

बड़ी टेबल पर सेल्फ ज्वाइनिंग टेबल बहुत तेज नहीं है। इसलिए PostgreSQL पर इस कार्य से निपटने के लिए मैंने संग्रहीत फ़ील्ड "शेष" की गणना के लिए ट्रिगर फ़ंक्शन का उपयोग करने का निर्णय लिया। सभी गणना प्रत्येक पंक्ति के लिए केवल एक बार होती है।

DROP TABLE IF EXISTS statements;

CREATE TABLE IF NOT EXISTS statements (
  id BIGSERIAL,
  stmnt_date TIMESTAMP,
  debit NUMERIC(18,2) not null default 0,
  credit NUMERIC(18,2) not null default 0,
  balance NUMERIC(18,2)
);

CREATE OR REPLACE FUNCTION public.tr_fn_statements_balance()
RETURNS trigger AS
$BODY$
BEGIN

    UPDATE statements SET
    balance=(SELECT SUM(a.debit)-SUM(a.credit) FROM statements a WHERE a.stmnt_date<=statements.stmnt_date)
    WHERE stmnt_date>=NEW.stmnt_date;

RETURN NULL;
END;
$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

CREATE TRIGGER tr_statements_after_update
  AFTER INSERT OR UPDATE OF debit, credit
  ON public.statements
  FOR EACH ROW
  EXECUTE PROCEDURE public.tr_fn_statements_balance();


INSERT INTO statements
(stmnt_date  , debit, credit) VALUES
('2014-06-17', 20000, 0     ),
('2014-08-14', 0    , 3000  ),
('2014-07-16', 0    , 3000  ),
('2015-02-01', 3000 , 0     ),
('2014-05-15', 3000 , 0     );


select * from statements order by stmnt_date;

-1

उदाहरण के लिए, MSSQL:

CTE जनरेट करने के लिए () स्टेटमेंट के साथ प्रयोग करें। यह अनिवार्य रूप से एक अस्थायी परिणाम सेट है जो प्रत्येक पंक्ति का मूल्य दिखाएगा। आप अंत में एक कॉलम बनाने के लिए गणित के साथ कथन का उपयोग कर सकते हैं, कुल पंक्ति को दिखाने के लिए गणित का उपयोग DEBIT-CREDIT है। आपके कथन के अनुसार आपको प्रत्येक पंक्ति में पंक्ति संख्याएँ निर्दिष्ट करने की आवश्यकता होगी, stmnt_tate द्वारा ऑर्डर करने के लिए () के OVER क्लॉज़ का उपयोग करें।

उसके बाद, पुन: तालिका को अपने आप से तालिका में शामिल करें। a .ROWNUMBER = b.ROWNUMBER-1 या +1 का उपयोग करके, जो आपको इस पंक्ति और पिछली पंक्ति के a.total + b.total = कुल का उल्लेख करने की अनुमति देगा।

मैं सराहना करता हूं कि मैं कोड प्रदान नहीं कर रहा हूं लेकिन इसे प्राप्त करने का व्यावहारिक तरीका है। मैं कोड की आपूर्ति कर सकते हैं अगर अनुरोध :)


1
सवाल MySQL के बारे में है। हालांकि यह बुरा नहीं है (इसके विपरीत) यह कोड प्रदान करने के लिए कि यह डीबीएमएस में सीटीई या विंडो फ़ंक्शन के साथ कैसे किया जा सकता है (जैसे पोस्टग्रेज, एसक्यूएल-सर्वर, डीबी 2, ओरेकल, ... सूची लंबी है), आप MySQL में ऐसा करने के बारे में कम से कम कोड प्रदान करना चाहिए।
ypercube y
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.