26 Ekim 2011 Çarşamba

Parametrik Top N Query

Parametreye bağlı olarak alacağımız selectteki top kısıtını değiştirmek dinamik query ile mümkündür fakat daha kısa bir yolu sözkonusudur.Gerçi bu yolu bundan 3 sene önce bulmuştum ama bir arkadaşımın hayır efendim bundan başka bir yolu yoktur demesiyle eski notlarımı karıştırdım.SQL dünyasına  olsun :)

select top @top * from #day

Bu sorguyu çalıştırmamız arkadaşımın iddiasına göre doğrudur çalışmaz.Fakat ufak bir değişiklik ile sorguyu çalışır hale getirebiliriz.Cevap : Alt Sorgu :) Herkese kolay gelsin...

select top (select @top) * from #day
top @top * from #day

ROWNUMBER()

Reporting services ile kaldığımız yerden devam ediyoruz.Raporlarda satır numarası vermek için microsoft bizim yerimize bir fonksiyon yapmış :) rownumber'ı aşağıdaki gibi bir rapor için kullanabiliriz.

1.Tablo Raporlarda
Kullanımı :
yeni bir cell yaratıp aşağıdaki formülü expressiona yazmak.

=ROWNUMBER("Missing_Sales") /Burada Missing sales dataset adımız
 


19 Ekim 2011 Çarşamba

Recovery Status

Backup ve restore şu sıralar sık sorun çıkarmaya başladı :(
bende tam olarak işim olmasada ilgilenmeye ve çözüm üretmeye çalışmaya başladım.
Arayüz kullanmadan joblarla backup yapınca recoverın ne durumda olduğunu görmemiz ancak sistem veritabanından alınan querylerle mümkün.Aşağıdaki query ile kodsal yaptığınız recover işleminin yüzdesini görebileceğiniz query mevcut


SELECT session_id as SPID, command, a.text AS Query, start_time, percent_complete, dateadd(second,estimated_completion_time/1000, getdate()) as estimated_completion_time
FROM sys.dm_exec_requests r CROSS APPLY sys.dm_exec_sql_text(r.sql_handle) a
WHERE r.command in ('BACKUP DATABASE','RESTORE DATABASE') 



Query çıktısı şu şekilde:



6 Eylül 2011 Salı

Reporting Services Kümülatif Toplam ve Running Value

Artan kümülatif değeri rapor içinde göstermek normal şartlarda query yada stored procedure ile mümkündür.Reporting serviceste table tipte bir raporumuz olduğunu düşünelim.Bu raporda satış ve adetin geldiğini düşünelim.Sales amountun artarak kendi içinde toplanması için RunningValue formülünü kullanabiliriz.Sales Amount ve Order Quantity kolonları arasına eklediğimiz boş alanın cell expressionuna

=RunningValue(Fields!SalesAmount.Value,Sum,"table1_SubCategory")

Formülünü yazarsak bu formül bize raporumuzdaki "table1_SubCategory" grubuna göre kümülatif olarak artan değerleri verecektir.

Örnekte Subcategory Cap ve Gloves vardır.Kümülatif değerin Gloves kategorisinde yeniden başladığına dikkat etmek gerekir.

21 Ağustos 2011 Pazar

Surrogate Keys ve Slowly Changing Dimension - 1

Bilindiği gibi veri ambarları fact ve dimension tablolaran oluşur.Veri ambarına aktarılan bilgilerin mümkün olduğunca ilgili,minimum verilerden oluşması gerekmektedir.Veri tipi optimizasyonuda veri ambarı oluşturulması sırasında önemli bir konudur.Şöyleki transactional veritabanından alınan ana veriler ve idler olduğu gibi veri ambarına aktarılırsa veri tipi optimizasyonu es geçilmiş olur.














Örneğin,ürün idsi (item_code) olarak transactional veri tabanı (OLTP) üzerinde char (10) kadar yer kaplasın ve bunun gibi maksimum 1000 adet ürün olduğunu düşünelim.Ürün dimension tablosunda char yada int olarak
durmasının fazla bir esprisi olmayacaktır.Bize alandan yer tasarrufu yapacak kısım fact tablosudur.Bir fact tablosuna bu ürüne ait hareket kayıtlarını tutarken char(10) kadar bir alan kaplayan alan kullanırsak 1 milyon kayıtta 10 bayt*1 milyon byte sadece 9,5 mb gibi yer kaplayacaktır.Eğer bunun yerine dimension tablomuzda int bir identity alan tanmılayıp referans olarak bu idyi fact tablosuna atsaydık 4 byte * 1 milyon = ~3.8 mb yer kaplayacaktır.

Şöyle dediğinizi duyar gibiyim.Depolama sistemleri çok gelişti ve mb hesabı yapmayın diyebilirsiniz.Bu kayıtları milyarlarca olabilieceğini,indexlemenin eklenmesiyle ek maliyetlerin gelebileceğini,fact tablosunda başka dimension referans id lerinin geleceğini göz ardı etmemek gerekir.

Başlangıçta bu tür optimizasyonlar  düşünülmez fakat daha sonrasında veriambarına ait veritabanımızın boyutu terabaytlara ulaşınca başta yapmamız gereken optimizasyonları sonradan yapmak zorudan kalabiliriz.

Sonuç olarak surrogate keys veriambarlarında kullanılması gereken bir concepttir.Kodlama yaparken de yük getireceğini düşünmüyorum.

Yöntem:

Ürnü bilgilerinin aşağıdaki gibi saklandığı dim_item tablosu olduğunu düşünelim.Auto increnmental (otomatik olarak artan) olarak tanımlandığını varsayıyorum ki kesin olarak her tabloda tekilliği (unique) sağlayan alan olmalı.Item_code ise oltp'den gelen id olsun.


DIM_ITEM
IDITEM_CODE
1D90*500478
2D90*500479
3D90*500480
.


Satışların tutulduğu fact_sales tablosunun içinde ürün referans olarak aşağıdaki gibi D90*500478 alınması yanlıştır.


FACT_SALES
ITEM_IDTRANS_DATEQTY
D90*50047821.08.20116
D90*50047921.08.20115
D90*50048021.08.201112



Bunun yerine dim_item tablosundaki id kolonu fact tablosuna kaydedilmelidir.Gerek duyulduğundan dimesion tablosu ile join edilerek D90*500478  bilgisine ulaşılabilir.


FACT_SALES
ITEM_IDTRANS_DATEQTY
121.08.20116
221.08.20115
321.08.201112

Bu tip bir veri aktarımını query yardımı ile yada etl tool olarak kullandığınız platformdaki dönüştürücülerle yapabilirsiniz.

Query ile :

insert into fact_sales (item_id,
                                trans_date,
                                qty)
select                    dim_item.id,
                             tmp_sales.trans_date,
                             tmp_sales.qty
   from tmp_sales
inner join dim_item on dim_item.item_code = tmp_sales.item_code
 
Microsoft  ETL çözümü integration services ( ssis ) için slowly changing dimesion ile bu dönüşümü kolayca yapabilirsiniz.Sonraki yazıda slowly changing dimesion kullanımını anlatacağım.

9 Ağustos 2011 Salı

LOGO Aktarım - VBA Kod Örnekleri

Bu kısımda Vba örnek ifadeleri yayınlıyorum.Logo xml oluşturuken aşağıdaki işlemleri yapmam gerekti bende size madde madde açıklamaya çalıştm.

1.Bir hücre ( cell ) değerini değişkene atama:

Aşağıdaki kod sheet 1 sayfasındaki 6.satır ve 2 sütunun kesişimindeki hücrenin değerini verir.

Worksheets("Sheet1").Cells(6, 2).Value

2. Excelde Son satırın numarasını bulmak :

Bunu transaction satırlarında kaç kere döngüye girmem gerektiğini bulmam için kullanmıştım.İfadede bulduğum son satır değerini int tipinde bir değişkene atıyorum.

lastRow = ActiveSheet.Cells.Find(What:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByRows).Row

3.Excelde kolonları toplama

Bana toplam borç ve alacak rakamları xml oluştururken lazım olacak.Dolayısı ile ilgili kolonları toplamam gerekiyor.Döngü (loop)yapmak VBA de çok basit öyleki döngü indisi için değişken tanımlamanıza bile gerek yok.Şöyleki , i döngü indisini ifade ediyor.Ayrıca i diye bir değişken declare etmem gerekli değil.
14.satırdan başlayıp son satır değerine kadar 7 kolondaki değerleri topluyorum.

For i = 14 To lastRow
        borc= borc+ Worksheets("Sheet1").Cells(i, 7).Value
    Next

4. Date ve Time Nesneleri

Oluşturduğum xml için zaman ve tarih bilgisine ihtiyacım vardı.Tarihi direk Date yazarak çağırabiliyorsunuz.Time' yazarak o anki saat,dakika ve saniye bilgileri geliyor.

Dim tarih as string       
tarih = Date
msgbox ("Tarih:" & tarih )

Bize "Tarih :09.08.2011" çıktısını verecek.
msgbox ("Tarih:" & Time)

Zaman ise 21:58:02 şekline çıktı verecek.Fakat ben saat,dakika ve saniyeyi ayrı ayrı olarak xmle eklemeliyim.Bu yüzden SQL  deki datepart() ile aynı özelliklere ve ada sahip fonksiyon işime yarayacak.

 MsgBox ("Saat:" & DatePart("h", Time) & " Dakika:" & DatePart("n", Time) & " Saniye:" & DatePart("m", Time))

5. If Else Örneği

Ben yaşadım siz yaşamayın :) if else yazaren katil oluyordum.En basit yazılım ifadelerinden if else yazarken then'den sonra enter'a basmayı unutmayın çünkü yanyana yazında hata ile karşılaşıyorsunuz.Sql ile sürekli uğraşan biri olarak bu hataya anlam veremedim.

If CLng(Borc) > 0 And CLng(Alacak) = 0 Then
            tmpTutar = Borc
            trType = 1
        ElseIf CLng(Alacak) > 0 And CLng(Borc) = 0 Then
            tmpTutar = Alacak
            trType = 2
        Else
            MsgBox ("Dikkat " & i - 14 & ". satır borc ve alacak alanları boş.")
        End If

Logo Aktarım - 2

Sıra geldi biraz kod yazmaya :)

Eğer Dynamics Ax gibi bir ERP yazılımına sahip değilseniz ya tecrübenizle yada iyi dökümanlarla aktarım yapmanız kolaylaşacaktır.Logo için dökümanı http://www.logotiger2.net/aktarimlar.pdf adresinde mevcut.BU döküman ne işimize yarayacak derseniz..
Bir önceki yazıda Logodan dışarı veri aktarmadan bahsetmiştik.Aktarımdan sonra oluşan xmle benzer xmller ile içeri vri aktarımı yapmak mümkün.Örneği biri sizden toplu virman fişi aktarımı istedi.Sizde örnek xml'i dışarı aktardınız.Buraya kadar problem yok fakat aşağıdaki gibi bir xmlde hangi alanın neye karşılık geldiğini bulmak zor olabilir.
Örnek virman fişi kodu şu şekilde:
<?xml version="1.0" encoding="ISO-8859-9" ?>
- <BANK_VOUCHERS>
- <BANK_VOUCHER DBOP="INS">
<DATE>06.06.2011</DATE>
<NUMBER>001545</NUMBER>
<AUXIL_CODE>KEREM</AUXIL_CODE>
<DEPARMENT>1</DEPARMENT>
<TYPE>2</TYPE>
<TOTAL_DEBIT>35000</TOTAL_DEBIT>
<TOTAL_CREDIT>35000</TOTAL_CREDIT>
<NOTES1>BANKA VİRMAN</NOTES1>
<CREATED_BY>47</CREATED_BY>
<DATE_CREATED>16.06.2011</DATE_CREATED>
<HOUR_CREATED>9</HOUR_CREATED>
<MIN_CREATED>32</MIN_CREATED>
<SEC_CREATED>24</SEC_CREATED>
<CURRSEL_TOTALS>1</CURRSEL_TOTALS>
<DATA_REFERENCE>136466</DATA_REFERENCE>
<RC_TOTAL_DEBIT>22189.82</RC_TOTAL_DEBIT>
<RC_TOTAL_CREDIT>22189.82</RC_TOTAL_CREDIT>
- <TRANSACTIONS>
+ <TRANSACTION>
<TYPE>1</TYPE>
<BANKACC_CODE>xxxxxxxxxxxxxxxx</BANKACC_CODE>
<GL_CODE2>102.100.001.0001</GL_CODE2>
<SOURCEFREF>136466</SOURCEFREF>
<DATE>06.06.2011</DATE>
<TRCODE>2</TRCODE>
<MODULENR>7</MODULENR>
<DESCRIPTION>BANKA VİRMAN</DESCRIPTION>
<DEBIT>20000</DEBIT>
<AMOUNT>20000</AMOUNT>
<TC_XRATE>1</TC_XRATE>
<TC_AMOUNT>20000</TC_AMOUNT>
<RC_XRATE>1.5773</RC_XRATE>
<RC_AMOUNT>12679.9</RC_AMOUNT>
<BANK_PROC_TYPE>1</BANK_PROC_TYPE>
<DUE_DATE>06.06.2011</DUE_DATE>
<DATA_REFERENCE>173071</DATA_REFERENCE>
<AFFECT_RISK>1</AFFECT_RISK>
<ORGLOGOID />
- <PAYMENT_LIST>
- <PAYMENT>
<DATA_REFERENCE>0</DATA_REFERENCE>
<DISCTRDELLIST>0</DISCTRDELLIST>
</PAYMENT>
</PAYMENT_LIST>
</TRANSACTION>
- <TRANSACTION>
<TYPE>1</TYPE>
<BANKACC_CODE>XXXXXXXXXXXXXXX</BANKACC_CODE>
<GL_CODE2>102.100.001.0001</GL_CODE2>
<SOURCEFREF>136466</SOURCEFREF>
<DATE>06.06.2011</DATE>
<TRCODE>2</TRCODE>

Buna benzer bir XML dosyası oluşturmak için ben aşağıdaki gibi bir excel hazırladım ve meşhur butonu ekledim :)


Bu butonun eventinde ise exceldeki verilere istinaden xml dosyamızı oluşturacak makro  yazılmıştır.Aslında kodlama oldukça basit.String bir değişkeni xmlenki her bir noda göre manipule ediyoruz.Başlık verileri (header veriler) sabit olduğundan döngüsel bir işlem yapılmıyor.Fakat transactionlar ekranda görülen bilgilerle oluşturuluyor.Ben xml oluştururken aşağıdaki şekilde stringi manipule ediyorum.Kod  xmle çok benzediğinden okuması daha kolay oluyor.








VBA Code örneği:

strXMLHEADER = "<?xml version=""1.0"" encoding=""ISO-8859-9"" ?> <BANK_VOUCHERS>" & vbCrLf
    strXMLHEADER = strXMLHEADER & " <BANK_VOUCHER DBOP=""INS"" >" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <DATE>" & Worksheets("Sheet1").Cells(6, 2).Value & "</DATE>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <NUMBER>~</NUMBER>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <AUXIL_CODE>" & Worksheets("Sheet1").Cells(4, 2).Value & "</AUXIL_CODE>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <DEPARTMENT>" & Worksheets("Sheet1").Cells(7, 2).Value & "</DEPARTMENT>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <TYPE>2</TYPE>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <TOTAL_DEBIT>" & sumTUTAR & "</TOTAL_DEBIT>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <TOTAL_CREDIT>" & sumTUTAR & "</TOTAL_CREDIT>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <NOTES1>" & sDESCRIPTION & "</NOTES1>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <CREATED_BY>" & Worksheets("Sheet1").Cells(5, 2).Value & "</CREATED_BY>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <DATE_CREATED>" & Date & "</DATE_CREATED>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <HOUR_CREATED>" & DatePart("h", Time) & "</HOUR_CREATED>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <MIN_CREATED>" & DatePart("n", Time) & "</MIN_CREATED>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <SEC_CREATED>" & DatePart("s", Time) & "</SEC_CREATED>" & vbCrLf
    strXMLHEADER = strXMLHEADER & "     <CURRSEL_TOTALS>1</CURRSEL_TOTALS>" & vbCrLf

Sabit değerleri direk yazdım.Parametrik olan ve excel aldığım kodları ise değişken olarak stringe ekledim.

Oluşan XMlide aşağıdaki gibi bir kod yardımıyla xml dosyasına çevirebilirsiniz.
Fonksiyon xml değişkeni dosya olarak saklamamızı sağlıyor.

Private Sub CreateFile(ByVal strFullFileName As String, ByVal strXML As String)

  Dim objStream As Object
 
  Set objStream = CreateObject("ADODB.Stream")
  objStream.Open
  objStream.Position = 0
  objStream.Charset = "ISO-8859-9" '"UTF-8"
  objStream.WriteText strXMLHEADER 
  objStream.SaveToFile strFullFileName, 2
 
End Sub