SAP Business One Hazır SQL Sorguları: Kopyala-Çalıştır 10 Örnek
SAP Business One için en çok aranan 10 hazır SQL: aktif müşteriler, depo bazında stok, aylık net satış, en çok satanlar, açık faturalar, bekleyen siparişler ve temsilci cirosu. Hepsi gerçek SAP B1 veritabanında test edildi.
Erp Asistanı
Editör ekibi
9 dk okuma
İçindekiler
SAP Business One'ın kendi rapor ekranları çoğu ihtiyacı karşılar; ama veriyi Excel'e, bir panoya ya da başka bir sisteme almak istediğinizde iş SQL'e düşer. Bu yazıda en çok aranan 10 SAP Business One raporunun hazır SQL karşılığını bulacaksınız: aktif müşteriler, depo bazında stok, aylık net satış, en çok satan ürünler, müşteri bazında ciro, açık faturalar, bekleyen siparişler, temsilci performansı, fiyat listesi ve tahsilatlar. Sorguların hepsi SAP'nin resmi Türkiye demo şirketinde (SAP Business One 10.0, SQL Server) çalıştırılarak test edildi; kopyalayıp kendi şirket veritabanınızda çalıştırabilirsiniz.
Başlamadan önce: dört kural
Bu dört kural sorguların neden öyle yazıldığını açıklar. Kendi sorgunuzu yazarken de aynısını uygulayın:
| Kural | Neden |
|---|---|
Her belge sorgusunda CANCELED = 'N' |
İptal edilen belge ile onu ters çeviren belge birlikte toplanmasın |
Net satış = OINV eksi ORIN |
Alacak dekontu (satış iadesi faturası) satıştan düşülür; irsaliye (ODLN) toplama eklenmez |
JOIN'ler DocEntry ve CardCode / ItemCode ile |
DocNum numara serisine göre tekrar edebilir |
Türkçe metin N'...' ile |
SAP'nin demo şirketinin collation'ında ş, ğ, İ yoktur; öneksiz literal sessizce bozulur |
Tablo adlarının ne anlama geldiğini merak ediyorsanız önce SAP Business One tablo yapısı rehberine bakın.
1. Aktif müşteri listesi
SELECT c.CardCode AS CariKod,
c.CardName AS CariAd,
g.GroupName AS CariGrubu,
c.LicTradNum AS VergiNo,
c.City AS Sehir,
c.Phone1 AS Telefon,
c.E_Mail AS EPosta
FROM OCRD c
LEFT JOIN OCRG g ON g.GroupCode = c.GroupCode
WHERE c.CardType = 'C' -- C müşteri, S tedarikçi, L aday
AND c.frozenFor = 'N' -- pasif kartlar hariç
ORDER BY c.CardName;
Tedarikçi listesi için CardType = 'S' yazmanız yeterli. Türkiye kurulumlarında vergi numarası ve TC kimlik numarası LicTradNum kolonunda durur.
2. Stok listesi ve toplam eldeki miktar
SELECT i.ItemCode AS StokKod,
i.ItemName AS StokAd,
b.ItmsGrpNam AS StokGrubu,
i.InvntryUom AS Birim,
i.OnHand AS Eldeki,
i.IsCommited AS SipariseAyrilan,
i.OnOrder AS Beklenen
FROM OITM i
LEFT JOIN OITB b ON b.ItmsGrpCod = i.ItmsGrpCod
WHERE i.InvntItem = 'Y' -- stoklu kalem (hizmet kartları hariç)
AND i.frozenFor = 'N'
ORDER BY i.ItemCode;
3. Depo bazında stok ve kullanılabilir miktar
SELECT w.ItemCode AS StokKod,
i.ItemName AS StokAd,
w.WhsCode AS Depo,
w.OnHand AS Eldeki,
w.OnHand - w.IsCommited + w.OnOrder AS Kullanilabilir,
w.MinStock AS MinimumStok
FROM OITW w
JOIN OITM i ON i.ItemCode = w.ItemCode
WHERE i.InvntItem = 'Y'
AND w.WhsCode = '01' -- depo kodu metindir: '01', 1 değil
ORDER BY w.OnHand DESC;
Bütün depoları görmek için WhsCode filtresini kaldırın. Minimum stok tanımlı kalemlerde kritik seviyeyi bulmak için AND w.MinStock > 0 AND w.OnHand < w.MinStock ekleyin.
4. Aylık net satış (KDV hariç, iadeler düşülmüş)
SELECT Yil, Ay, SUM(Tutar) AS NetSatisKdvHaric
FROM (
SELECT YEAR(DocDate) AS Yil, MONTH(DocDate) AS Ay, DocTotal - VatSum AS Tutar
FROM OINV
WHERE CANCELED = 'N'
UNION ALL
SELECT YEAR(DocDate), MONTH(DocDate), -(DocTotal - VatSum)
FROM ORIN
WHERE CANCELED = 'N'
) s
WHERE Yil >= YEAR(GETDATE()) - 1
GROUP BY Yil, Ay
ORDER BY Yil, Ay;
DocTotal KDV dahil belge toplamıdır; DocTotal - VatSum belge altı indirim düşülmüş KDV hariç tutarı verir. Tutarlar yerel para birimindedir; dövizli faturanın döviz tutarı DocTotalFC kolonundadır.
5. En çok satan 10 ürün (son 12 ay)
SELECT TOP 10
s.ItemCode AS StokKod,
i.ItemName AS StokAd,
SUM(s.Miktar) AS NetSatilanMiktar,
SUM(s.Tutar) AS NetTutar
FROM (
SELECT l.ItemCode, l.Quantity AS Miktar, l.LineTotal AS Tutar
FROM INV1 l
JOIN OINV f ON f.DocEntry = l.DocEntry
WHERE f.CANCELED = 'N' AND f.DocDate >= DATEADD(MONTH, -12, CAST(GETDATE() AS date))
UNION ALL
SELECT l.ItemCode, -l.Quantity, -l.LineTotal
FROM RIN1 l
JOIN ORIN r ON r.DocEntry = l.DocEntry
WHERE r.CANCELED = 'N' AND r.DocDate >= DATEADD(MONTH, -12, CAST(GETDATE() AS date))
) s
JOIN OITM i ON i.ItemCode = s.ItemCode
GROUP BY s.ItemCode, i.ItemName
ORDER BY NetSatilanMiktar DESC;
Ürün adını belge satırından (Dscription) değil karttan (OITM.ItemName) alıyoruz: satırdaki açıklama belgede elle değiştirilmiş olabilir ve aynı ürün raporda iki ayrı satıra bölünür.
6. Müşteri bazında ciro (bu yıl, ilk 10)
SELECT TOP 10
s.CardCode AS CariKod,
c.CardName AS CariAd,
SUM(s.Tutar) AS NetCiroKdvHaric
FROM (
SELECT CardCode, DocTotal - VatSum AS Tutar
FROM OINV
WHERE CANCELED = 'N' AND DocDate >= DATEFROMPARTS(YEAR(GETDATE()), 1, 1)
UNION ALL
SELECT CardCode, -(DocTotal - VatSum)
FROM ORIN
WHERE CANCELED = 'N' AND DocDate >= DATEFROMPARTS(YEAR(GETDATE()), 1, 1)
) s
JOIN OCRD c ON c.CardCode = s.CardCode
GROUP BY s.CardCode, c.CardName
ORDER BY NetCiroKdvHaric DESC;
7. Ödenmemiş (açık) satış faturaları
SELECT f.DocNum AS FaturaNo,
f.CardCode AS CariKod,
c.CardName AS CariAd,
f.DocDate AS Tarih,
f.DocDueDate AS Vade,
f.DocTotal AS FaturaTutari,
f.PaidToDate AS Odenen,
f.DocTotal - f.PaidToDate AS Kalan,
DATEDIFF(DAY, f.DocDueDate, CAST(GETDATE() AS date)) AS GecikmeGunu
FROM OINV f
JOIN OCRD c ON c.CardCode = f.CardCode
WHERE f.CANCELED = 'N'
AND f.DocStatus = 'O' -- O açık, C kapalı (tamamen ödenmiş)
ORDER BY GecikmeGunu DESC;
GecikmeGunu negatifse fatura henüz vadesine gelmemiştir. Yaşlandırma kovaları (0-30, 31-60, 61-90, 90+) ve yevmiyeden bakiye hesabı için SAP Business One cari bakiye ve yaşlandırma SQL yazısına bakın.
8. Bekleyen (açık) satış siparişleri
SELECT o.DocNum AS SiparisNo,
o.DocDate AS SiparisTarihi,
o.CardCode AS CariKod,
c.CardName AS CariAd,
l.ItemCode AS StokKod,
l.Quantity AS SiparisMiktari,
l.OpenQty AS KalanMiktar,
l.ShipDate AS TeslimTarihi
FROM ORDR o
JOIN RDR1 l ON l.DocEntry = o.DocEntry
JOIN OCRD c ON c.CardCode = o.CardCode
WHERE o.CANCELED = 'N'
AND l.LineStatus = 'O'
AND l.OpenQty > 0
ORDER BY l.ShipDate, o.DocNum;
Kısmen sevk edilmiş satırda OpenQty yalnız kalan miktarı gösterir. Söz verilen tarihi geçmiş siparişler için AND l.ShipDate < CAST(GETDATE() AS date) ekleyin.
9. Satış temsilcisi bazında ciro (bu yıl)
SELECT s.SlpName AS Temsilci,
COUNT(*) AS FaturaSayisi,
SUM(f.DocTotal - f.VatSum) AS CiroKdvHaric
FROM OINV f
JOIN OSLP s ON s.SlpCode = f.SlpCode
WHERE f.CANCELED = 'N'
AND f.DocDate >= DATEFROMPARTS(YEAR(GETDATE()), 1, 1)
GROUP BY s.SlpName
ORDER BY CiroKdvHaric DESC;
SlpCode = -1 "temsilci yok" kaydıdır; temsilcisiz faturaları ayrı görmek istemiyorsanız AND f.SlpCode <> -1 ekleyin. Bu sorgu iadeleri düşmez; iade düşülmüş temsilci cirosu için 6. sorgudaki UNION ALL kalıbını SlpCode ile kurun.
10. Fiyat listesine göre ürün fiyatları
SELECT i.ItemCode AS StokKod,
i.ItemName AS StokAd,
p.ListName AS FiyatListesi,
f.Price AS Fiyat,
f.Currency AS ParaBirimi
FROM ITM1 f
JOIN OITM i ON i.ItemCode = f.ItemCode
JOIN OPLN p ON p.ListNum = f.PriceList
WHERE i.SellItem = 'Y'
AND i.frozenFor = 'N'
AND f.PriceList = 1 -- kendi fiyat listenizin numarası (OPLN.ListNum)
ORDER BY i.ItemCode;
Fiyat listelerinizi SELECT ListNum, ListName, IsGrossPrc FROM OPLN ile görebilirsiniz. IsGrossPrc = 'N' olan listede fiyatlar KDV hariçtir.
Bonus: son 30 günün tahsilatları
SELECT r.DocNum AS TahsilatNo,
r.DocDate AS Tarih,
r.CardCode AS CariKod,
c.CardName AS CariAd,
r.CashSum AS Nakit,
r.TrsfrSum AS Havale,
r.CheckSum AS Cek,
r.CreditSum AS KrediKarti,
r.CashSum + r.TrsfrSum + r.CheckSum + r.CreditSum AS Toplam
FROM ORCT r
JOIN OCRD c ON c.CardCode = r.CardCode
WHERE r.Canceled = 'N'
AND r.DocDate >= DATEADD(DAY, -30, CAST(GETDATE() AS date))
ORDER BY r.DocDate DESC;
Tahsilat tablosunda iptal kolonu CANCELED değil Canceled olarak yazılır (SQL Server'da varsayılan olarak büyük/küçük harf fark etmez, ama kolonun adını doğru bilmek kodu okunur kılar).
Sık yapılan hatalar
- İrsaliye ile faturayı birlikte toplamak: fatura irsaliyeden kopyalandıysa satış iki kez sayılır. Ciro faturadan (
OINV - ORIN) alınır. DocTotal'ı KDV hariç sanmak:DocTotalKDV dahildir. KDV hariç tutarDocTotal - VatSumya da satır toplamı (LineTotal) ile alınır.- Depo koduna sayı yazmak:
WhsCode = 1sorgusu'01'deposunu bulmaz. - Türkçe aramayı
Nöneksiz yazmak:LIKE '%Şahin%'hata vermez, boş ya da yanlış sonuç döner.LIKE N'%Şahin%'yazın. - Pasif kartları listeye almak: dondurulmuş (pasif) cari ve stok kartlarında
frozenFor = 'Y'olur.
Sık sorulanlar
Bu sorgular SAP Business One'ın hangi sürümünde çalışır? Sorgular SAP Business One 10.0'ın SQL Server sürümünde test edildi. Kullanılan tablolar (OINV, OCRD, OITM, OITW, ORDR, ORCT) uzun yıllardır aynı adla duruyor; 9.x sürümlerinde de büyük ölçüde aynen çalışır. HANA sürümünde ise tarih fonksiyonları (DATEADD, DATEFROMPARTS) farklıdır ve tablo/kolon adları çift tırnakla yazılır; bu sorgular orada uyarlanmadan çalışmaz.
SQL'i nerede çalıştırmalıyım? SQL Server Management Studio'da, SAP Business One şirketinizin veritabanı seçiliyken çalıştırın. Bu sorguların hepsi yalnız okuma yapar. SAP Business One veritabanına doğrudan INSERT, UPDATE ya da DELETE yazmayın; SAP veri yazmayı yalnız kendi arayüzü, DI API ve Service Layer üzerinden destekler.
Sorguyu SAP içindeki Sorgu Yöneticisi'nde kullanabilir miyim? Evet, SELECT sorgularını Sorgu Yöneticisi'ne (Query Manager) kaydedebilirsiniz. DECLARE ile değişken tanımlanan sorgularda değişkeni sabit değerle değiştirmeniz ya da SAP'nin [%0] parametre sözdizimini kullanmanız gerekir.
Ciro raporum SAP ekranındaki rakamla tutmuyor, neden? En sık üç sebep: iadelerin (ORIN) düşülmemesi, KDV dahil (DocTotal) ile KDV hariç tutarın karıştırılması ve iptal belgelerin (CANCELED) filtrelenmemesi. Ayrıca SAP raporları belge tarihi (DocDate) yerine vergi tarihine (TaxDate) göre filtrelenmiş olabilir.
Her rapor için sorgu uyarlamakla uğraşmak istemiyorsanız sorunuzu Türkçe yazın: Erp Asistanı SAP Business One şemanıza uygun, doğrulanmış SQL'i saniyeler içinde üretir. Nasıl çalıştığını SQL Üretme rehberinde görebilirsiniz.
SAP Business One'da SQL ve raporu konuşarak alın
Türkçe sorunuzu yazın, şemanıza uygun çalışan SQL'i ya da hazır uygulamanızı saniyeler içinde alın.