GROUP BY İşleminde SUM’a Değişken Atayamama Hatası
SORU:
Sorgu hata mesajı vermiyor, fakat bakiye sürekli sıfır çıkıyor.
Başlangıçtaki set sıfırları kaldırdığım zaman ise bakiye listenin en sonundakinin stok bakiye değerini alıyor.
O da ilk çalıştığında null oluyor, ikinci kez çalıştığında ancak o değeri veriyor.
Veritabanı Yapısı ve Örnek Kodlamayı görmek için tıklayınız.
Set @deggiren =0; Set @degcikan =0; Set @bakiye =0; select *, (@deggiren := sum(if(STKHARTIPI=1,STKHARMIKTAR,0))) AS GIREN, (@degcikan := sum(if(STKHARTIPI=2,STKHARMIKTAR,0))) AS CIKAN, @deggiren - @degcikan = @bakiye, @bakiye as BAKIYE from dbo_stkhar LEFT JOIN dbo_stkkart ON STKHARSTKKOD=STKKOD where STKHARCALFLAG=1 AND STKHARISLEMTIP=1 AND @bakiye > 0 group by STKHARSTKKOD
CEVAP:
SET ile yapılan sorgulamalarda işlemler iki adımda çalışmaktadır. Burada çalıştırdığınız ilk zaman değerler sizinde dediğiniz gibi ilgili değişkene atanır. Tekrardan ilgili değişkeni kullanarak istediğiniz işlemler yapılmaktadır.
En basit örneğini buraya tıklayarak görebilirsiniz.
Sorgunuzdaki mantığa istinaden aşağıdaki gibi bir sql sorgusu işinize yarayacaktır:
SELECT sum( if(STKHARTIPI=1,STKHARMIKTAR,0) ) AS GIREN, sum( if(STKHARTIPI=2,STKHARMIKTAR,0) ) AS CIKAN, sum( if(STKHARTIPI=1,STKHARMIKTAR,0) ) - sum( if(STKHARTIPI=2,STKHARMIKTAR,0) ) AS bakiye FROM dbo_stkhar WHERE STKHARCALFLAG=1 AND STKHARISLEMTIP=1 GROUP BY STKHARSTKKOD HAVING GIREN-CIKAN > 0;
Bu soruyu gönderen benim, sizlere çok teşekkür ederim. Bu şekliyle işime yarayacaktır. Peki ısrarla değişken kullanmak istersek nasıl olur? Veya kullanmasak daha iyimi olur?(performans açısından)
Değişken kullanmak isterseniz sorgunuz dediniz şekilde çalıştırdıktan sonra tekrardan bir sorgu atarak sadece ilgili değişkenleri almanız yeterli olacaktır.
Eğer PHP ile yapıyorsanız en basit örneği aşağıdaki gibidir. Burada işleyiş ilk önce değer atama daha sonra değeri alma gibi düşünebilirsiniz.
$dblink = mysql_connect(‘localhost’,’root’,’123456′);
mysql_query(‘SET @user := 123456;’);
$result = mysql_query(‘SELECT @user’);
$row = mysql_fetch_object( $result );
print_r( $row );
Performans açısından herhangi bir şey diyemeyeceğim açıkçası.
HAVING GIREN-CIKAN > 0;
yazmanızın özel bir nedeni varmı? Ben şu şekilde denedim sorun çıkarmadı,
HAVING BAKIYE > 0;
Birde order by BAKIYE ASC yazıyorum, sorun olmaz değil mi?
Hayır herhangi bir sorun olmayacaktır. İkisi de hemen hemen aynı şeydir zaten.
aşağıdaki sorguda dikkat ederseniz dört kere sum işlemi yapıyoruz.
girenleri ayrı topluyoruz, çıkanları ayrı topluyoruz(bunlar listelemek için)
daha sonra girenden çıkanı çıkarmak için birdaha topluyoruz. Benim amacım listelemek için giren ve çıkanı topladığımda bunları değişkene atayıp, sonra değişken den çıkarma işlemini yapmaktı. Bu sorgu ya sonra ekleyeceğim hurda ve giren çıkan zimmet toplamları da olacak, o zaman kasılacağını düşünüyorum. Group by işlemi olunca nedense sum doğru çalışmıyor. Bu sorgu yu direkt fast reporta aktarıyorum, php henüz kullanmıyoruz.
ama olmaz ise bu şekilde kullanmaya çalışacağım, buna şükür.
Teşekkür ederim ilginize…
SELECT *,
sum(if(STKHARTIPI=1,STKHARMIKTAR,0)) AS GIREN,
sum(if(STKHARTIPI=2,STKHARMIKTAR,0)) AS CIKAN,
sum(if(STKHARTIPI=1,STKHARMIKTAR,0)) – sum(if(STKHARTIPI=2,STKHARMIKTAR,0)) AS BAKIYE,
FROM dbo_stkhar
WHERE STKHARCALFLAG=1 AND STKHARISLEMTIP=1
GROUP BY STKHARSTKKOD
HAVING BAKIYE > 0 ORDER BY BAKIYE ASC;
Bu şekilde izin vermeyecektir. Aşağıdaki sorgu işinizi görür diye düşünüyorum.
Ama ben değişkene atayıp yapmak istiyorum diyorsanız yukarıdaki sorguyu 3. SUM işlemi hariç değişkenlere atayıp sonradan o değerleri çekmeniz yeterli olacaktır.
SELECT UCRET.GIREN,UCRET.CIKAN,(UCRET.GIREN-UCRET.CIKAN) as BAKIYE
FROM (
SELECT
SUM(if(STKHARTIPI=1,STKHARMIKTAR,0)) AS GIREN,
SUM(if(STKHARTIPI=2,STKHARMIKTAR,0)) AS CIKAN
FROM dbo_stkhar
WHERE STKHARCALFLAG=1 AND STKHARISLEMTIP=1
GROUP BY STKHARSTKKOD
) as UCRET
HAVING BAKIYE > 0
ORDER BY BAKIYE ASC
Benim daha önce kullandığım sorgu yaklaşık bu şekilde ydi.
Fakat sub query kullanmanın 60.000 kayıttan sonra persofmansı
ciddi şekilde sarstığını öğrendim. O yüzden sub queryi kaldırdım.
Bu sizin yaptığınız sorgu aşağıdaki sorgudan farklımı siz ce?
Eğer farklı ise sizin sorguyu kullanayım.
Select * from(select *,
sum(if(STKHARTIPI=1,STKHARMIKTAR,null)) AS GIREN,
sum(if((STKHARTIPI=2) OR (STKHARTIPI=3),STKHARMIKTAR,null)) AS CIKAN,
sum(if(STKHARTIPI=-1,STKHARMIKTAR,null)) AS DEVIR,
sum(if(STKHARTIPI=1,STKHARMIKTAR,0)-if((STKHARTIPI=2) OR (STKHARTIPI=3),STKHARMIKTAR,0)) AS BAKIYE
from dbo_stkhar where STKHARCALFLAG=1 AND STKHARISLEMTIP=1
group by STKHARSTKKOD) AS TMP
LEFT JOIN dbo_stkkart as k ON STKHARSTKKOD=k.STKKOD
where BAKIYE>0
Peki GIREN veya CIKAN alanlarına değişken atayabilirmiyiz.
Olmaz ise GIREN – CIKAN AS BAKIYE de işlemide işime yarar.
as ile yapılan tanımlamalarda aynı sorguda işlemi tanımamaktadır.
Sanırım bir üst cevap işinizi görecek.