MS SQL Yürüyen Bakiye Sorunu
#1
öncelikle merhaba Muhasebe ile ilgili bir yazılım üzerinde çalışıyorum vb de

Yürüyen Bakiye ile ilgili birçok sorun ve birçok çözüm önerisi okudum ancak bu yorumların hemen hemen hepsinde,

bakiyeyi alırken başvurduğumuz benzersiz ID alanı oluyor. ancak muhasebenin işleyişinde neredeyse tüm raporlar tarih sırasına göre alınır. yani ID>=5 te bakiye ne kadardı değil. 05/05/2012 tarihinde bakiye ne kadardı diye sorgulanır.

bu noktada ID üzerinden işlem yapıldığında, eğer kullanıcı birkaç işlem sonra tarihi geriye dönük bir işlem girdiğinde, tarihi eski ama ID si yeni olduğundan sorunlar yaşıyoruz. örneğin;

ID TARİH BORÇ ALACAK BAKİYE

1 02.02.2012 100,00 0,00 100,00

6 04.04.2012 0,00 150,00 -50,00

3 02.05.2012 70,00 0,00 20,00

4 02.05.2012 80,00 0,00 100,00

2 06.06.2012 120,00 0,00 220,00

şeklinde bakiye verebilmeli, ID alanı kendiliğinden artan bir alan olduğundan bu alana müdahale etme şansım yok. ancak herhangi birşekilde kullanıcı eski tarihli bir işlem girdiğinde işler karışıyor

ID si 2 olan kaydın tarihi 06.06.2012 ancak ID si 6 olan kaydın tarihi 04.04.2012 olursa listeleme tarih sırasına göre yapıldığında bakiye alma konusunda sorun yaşanıyor. en kötü ihtimalle aynı gün içerisinde 2 kayıt olduğunda bakiye formulü bozuluyor. projemde takıldığım en büyük nokta bu.

bu konuda tek çözüm geçici tablo kullanımı yada yazarken vb içerisinde hesaplatmak gibi gözüküyor. ama geçici tablo kullanımı da çok hızlı bir çözüm olmuyor maalesef.

Şimdiden Teşekkürler,


Saygılar,




  Alıntı
Bu mesajı beğenenler:
#2
(20-12-2012, 22:39)trkmml demiş ki: .
.
bu konuda tek çözüm geçici tablo kullanımı yada yazarken vb içerisinde hesaplatmak gibi gözüküyor. ama geçici tablo kullanımı da çok hızlı bir çözüm olmuyor maalesef.

Bence hiç öyle düşünmeyin. Bir veritabanı performansını en çok tasarım etkiler. Geçici tablo oldukça hızlıdır.

Bakınız burada running sum performansı bile birkaç yolla test edilmiş.

http://www.access-sql.com/Konu-SQL-Serve...yen-Bakiye

Ben de mizan için hazırlamıştım. Yaklaşık 1-2 sn. sürüyor. Aynı mizan crystal report ile 2-3 dk. arasındadır. Ayrıca uzun query yazmaktan korkmayın. Fikir vermesi Likom Gusto ERP için yazdığım mizan sorgum aşağıdadır. Kolay gelsin.

SQL
  1. SET NOCOUNT ON
  2.  
  3. DECLARE @BASTAR SMALLDATETIME, @SONTAR SMALLDATETIME, @FLAGS SMALLINT, @KEBIR SMALLINT
  4. SET @BASTAR = '01.01.2012'
  5. SET @SONTAR = '30.11.2012'
  6. SET @FLAGS = 1
  7. SET @KEBIR = 0
  8.  
  9. -- Varsa geçici tabloyu sil
  10. IF EXISTS(SELECT * FROM tempdb.dbo.sysobjects O
  11. WHERE O.xtype = 'U' AND O.id = OBJECT_ID(N'tempdb..#TMP'))
  12. BEGIN
  13. DROP TABLE #TMP
  14. END
  15.  
  16. -- Yeni bir geçici tablo hazırla
  17. CREATE TABLE #TMP
  18. (
  19. [HESAP KODU] VARCHAR(20),
  20. [HESAP ADI] VARCHAR(255),
  21. [BORÇ TOPLAM] DECIMAL(18,2),
  22. [ALACAK TOPLAM] DECIMAL(18,2),
  23. [BORÇ BAKİYE] AS CASE
  24. WHEN [BORÇ TOPLAM]-[ALACAK TOPLAM] > 0 THEN [BORÇ TOPLAM]-[ALACAK TOPLAM] END,
  25. [ALACAK BAKİYE] AS CASE
  26. WHEN [ALACAK TOPLAM]-[BORÇ TOPLAM] > 0 THEN [ALACAK TOPLAM]-[BORÇ TOPLAM] END
  27. )
  28.  
  29. -- Geçici tablo için index hazırla
  30. CREATE CLUSTERED INDEX IDX11 ON #TMP([HESAP KODU])
  31.  
  32. -- Alt hesapların Borç ve Alacak toplamlarını geçici tabloya aktar
  33. INSERT INTO #TMP
  34. (
  35. [HESAP KODU],
  36. [HESAP ADI],
  37. [BORÇ TOPLAM],
  38. [ALACAK TOPLAM]
  39. )
  40. SELECT
  41. D.sKod AS [HESAP KODU],
  42. D.sAd AS [HESAP ADI],
  43. CAST(SUM(D.[BORC]) AS DECIMAL(18,2)) AS [BORÇ TOPLAM] ,
  44. CAST(SUM(D.[ALACAK]) AS DECIMAL(18,2)) AS [ALACAK TOPLAM]
  45. FROM
  46. (
  47. SELECT
  48. A.sKod,
  49. A.sAd,
  50. CASE C.bBorcMu WHEN 'B' THEN C.ldTutar ELSE 0 END AS [BORC],
  51. CASE C.bBorcMu WHEN 'A' THEN C.ldTutar ELSE 0 END AS [ALACAK]
  52. FROM HesapKodu A
  53. INNER JOIN YevmiyeHareketi C ON (A.HesapKodu_rowid = C.pHesapKodu)
  54. INNER JOIN YevmiyeFisi B ON ((C.lFisNo = B.lFisNo) AND (C.dtTarih = B.dtTarih))
  55. WHERE (B.dtTarih BETWEEN @BASTAR AND @SONTAR) AND (B.cCinsi @IN(0,1,2) )
  56. ) AS D
  57. GROUP BY D.sKod, D.sAd
  58.  
  59. -- Ana hesapların toplamlarını da geçici tablodan topla ve
  60. -- yine geçici tabloya ekle
  61. INSERT INTO #TMP
  62. (
  63. [HESAP KODU],
  64. [HESAP ADI],
  65. [BORÇ TOPLAM],
  66. [ALACAK TOPLAM]
  67. )
  68. SELECT
  69. E.sKod,
  70. E.sAd,
  71. SUM(F.[BORÇ TOPLAM]) AS [BORÇ TOPLAM],
  72. SUM(F.[ALACAK TOPLAM]) AS [ALACAK TOPLAM]
  73. FROM HesapKodu E INNER JOIN #TMP F ON (F.[HESAP KODU] LIKE E.sKod + '%')
  74. WHERE E.nChildCount > 0
  75. GROUP BY E.sKod, E.sAd
  76.  
  77. -- Son şeklini almış hale gelen geçici tabloyu listele
  78. IF (@FLAGS = 1)
  79. BEGIN
  80. IF (@KEBIR = 1)
  81. SELECT
  82. [HESAP KODU], [HESAP ADI],
  83. NULLIF([BORÇ TOPLAM], 0) AS [BORÇ TOPLAM],
  84. NULLIF([ALACAK TOPLAM], 0) AS [ALACAK TOPLAM],
  85. [BORÇ BAKİYE], [ALACAK BAKİYE]
  86. FROM #TMP
  87. WHERE (LEN([HESAP KODU]) = 3) ORDER BY [HESAP KODU]
  88. ELSE
  89. SELECT
  90. [HESAP KODU], [HESAP ADI],
  91. NULLIF([BORÇ TOPLAM], 0) AS [BORÇ TOPLAM],
  92. NULLIF([ALACAK TOPLAM], 0) AS [ALACAK TOPLAM],
  93. [BORÇ BAKİYE], [ALACAK BAKİYE]
  94. FROM #TMP ORDER BY [HESAP KODU]
  95. END
  96. ELSE
  97. BEGIN
  98. IF (@KEBIR = 1)
  99. SELECT
  100. [HESAP KODU], [HESAP ADI],
  101. NULLIF([BORÇ TOPLAM], 0) AS [BORÇ TOPLAM],
  102. NULLIF([ALACAK TOPLAM], 0) AS [ALACAK TOPLAM],
  103. [BORÇ BAKİYE], [ALACAK BAKİYE]
  104. FROM #TMP
  105. WHERE ([BORÇ TOPLAM] != [ALACAK TOPLAM] AND LEN([HESAP KODU]) = 3) ORDER BY [HESAP KODU]
  106. ELSE
  107. SELECT
  108. [HESAP KODU], [HESAP ADI],
  109. NULLIF([BORÇ TOPLAM], 0) AS [BORÇ TOPLAM],
  110. NULLIF([ALACAK TOPLAM], 0) AS [ALACAK TOPLAM],
  111. [BORÇ BAKİYE], [ALACAK BAKİYE]
  112. FROM #TMP
  113. WHERE ([BORÇ TOPLAM] != [ALACAK TOPLAM]) ORDER BY [HESAP KODU]
  114. END
  115.  
  116. -- Geçici tabloyu artık sil
  117. DROP TABLE #TMP






  Alıntı
Bu mesajı beğenenler:
#3
cevap için teşekkür ederim
aşağıdaki gibi bir yöntem ile sorunumu çözdüm.

SELECT [ID], [TARIH], [BORC], [ALACAK]
, Sum([BORC] - [ALACAK]) OVER (ORDER BY [TARIH], [ID]) AS [BAKIYE]
FROM DENEME



  Alıntı
Bu mesajı beğenenler:
#4
SELECT [ID], [TARIH], [BORC], [ALACAK], Sum([BORC] - [ALACAK]) OVER (ORDER BY [TARIH], [ID]) AS [BAKIYE] FROM DENEME

SORGUSUNDA

ÖZDİZİMİ HATASI VERİYOR. SEBEBİNİ NEDİR ACABA.

TEŞEKKÜR EDERİM.



  Alıntı
Bu mesajı beğenenler:
#5
"Over", sql server 2012 ve üzeri versiyonlarda eklenmiştir. Öncekilerde yalnız "partition" vardı.



  Alıntı
Bu mesajı beğenenler:


Benzer Konular...
Konu: Yazar Cevaplar: Gösterim: Son Mesaj
  sql server 2008 yürüyen bakiye ozkbilgi 3 2.380 18-08-2016, 14:10
Son Mesaj: ozkbilgi
  sql localdb yürüyen bakiye sorunu dabbetülarz 5 2.904 31-12-2012, 23:41
Son Mesaj: dabbetülarz
  SQL Server Running Sum (Yürüyen Bakiye) beab05 12 16.869 02-05-2012, 10:21
Son Mesaj: bybarone

Foruma Git:


Bu konuyu görüntüleyen kullanıcı(lar): 1 Ziyaretçi