SQL Server Indonesia User Groups Community April 2009 - Posts - Cahyo drop in {here}

SQL Server Indonesia User Groups Community

SQL Server Indonesia User Groups Community
Welcome to SQL Server Indonesia User Groups Community Sign in | Join | Help
in Search

Cahyo drop in {here}

SQL as breakfast, BI for lunch and dinner with MDX

April 2009 - Posts

  • The way I used CTE....

    Dalam tulisan kali ini saya ingin berbagi pengalaman saya tentang penggunaan CTE. dan pengalaman ini membuat saya CTE minded Big Smile...

    I love CTE Embarrassed

    Sebelumnya saya sudah mengajarkan jurus ini kepada beberapa teman. Pada umumnya mereka bilang jurus ini ampuh. Tapi bagi saya jurus ini MTV Ampuh Banget.

     

    Saya akan berbagi tentang jurus ini dengan menggunakan skenario pembuatan report untuk data penjualan.Pada report ini kita akan melihat penjualan untuk 1 bulan, penjualan pada bulan sebelumnya, penjualan dari awal kuartal sampai bulan sekarang, penjualan dari kuartal sebelumnya, dan penjualan dari awal tahun sampai bulan skarang.

    Supaya lebih sederhana dan mudah dimengerti saya buat tabel Sales dengan 3 kolom saja yaitu Product, SalesDate dan Quantity. Berikut script untuk tabelnya:

    CREATE TABLE #Sales (
        Product varchar(20),
        SalesDate datetime,
        Quantity int
    )

    Setelah itu kita buat beberapa data dummy data untuk table tersebut

    INSERT INTO #Sales
        SELECT 'CD',cast('20080101' AS datetime),1 UNION
        SELECT 'DVD','20080102',1 UNION
        SELECT 'Flash Disk','20080103',1 UNION
        SELECT 'Hard Disk','20080104',1 UNION

        SELECT 'CD','20080201',2 UNION
        SELECT 'DVD','20080202',2 UNION
        SELECT 'Flash Disk','20080203',2 UNION
        SELECT 'Hard Disk','20080204',2 UNION

        SELECT 'CD','20080301',3 UNION
        SELECT 'DVD','20080302',3 UNION
        SELECT 'Flash Disk','20080303',3 UNION
        SELECT 'Hard Disk','20080304',3 UNION

        SELECT 'CD','20080401',4 UNION
        SELECT 'DVD','20080402',4 UNION
        SELECT 'Flash Disk','20080403',4 UNION
        SELECT 'Hard Disk','20080404',4 UNION

        SELECT 'CD','20080501',5 UNION
        SELECT 'DVD','20080502',5 UNION
        SELECT 'Flash Disk','20080503',5 UNION
        SELECT 'Hard Disk','20080504',5

    Skarang kita sudah punya sumber data. Berikutnya adalah bagian query untuk reportnya. Disinilah saya akan menunjukkan cara saya memanfaatkan CTE yang ada pada SQL Server 2005 ke atas. Pada query ini saya menggunakan range periode bulan,kuartal dan tahun seperti pada postingan saya sebelumnya. Dan querynya seperti ini :

    DECLARE @pRequestPeriod char(6)
    SET @pRequestPeriod='200805'

    DECLARE @pDate datetime
    SET @pDate=@pRequestPeriod+'01'

    DECLARE @startMonth datetime,@endMonth datetime,@startPrevMonth datetime,@endPrevMonth datetime,
        @startQTM datetime,@endQTM datetime,@startPrevQTM datetime,@endPrevQTM datetime,
        @startYTM datetime,@endYTM datetime,@startPrevYTM datetime,@endPrevYTM datetime,@startPrevMoY datetime,@endPrevMoY datetime;

    SET @startMonth=datename(year,@pDate)+'-'+datename(month,@pDate)+'-01'
    SET @endMonth=dateadd(day,-1,dateadd(month,1,@startMonth))
    SET @startPrevMonth=datename(year,dateadd(month,-1,@pDate))+'-'+datename(month,dateadd(month,-1,@pDate))+'-01'
    SET @endPrevMonth=dateadd(day,-1,@startMonth)

    SET @startQTM=datename(year,@pDate)+'-'+cast(((datepart(month,@pDate)-1)/3)*3+1 AS varchar(2))+'-01'
    SET @endQTM=dateadd(day,-1,dateadd(month,1,datename(year,@pDate)+'-'+datename(month,@pDate)+'-01'))
    SET @startPrevQTM=datename(year,dateadd(month,-3,@pDate))+'-'+cast(((datepart(month,dateadd(month,-3,@pDate))-1)/3)*3+1 AS varchar(2))+'-01'
    SET @endPrevQTM=dateadd(day,-1,dateadd(month,1,datename(year,dateadd(month,-3,@pDate))+'-'+datename(month,dateadd(month,-3,@pDate))+'-01'))

    SET @startYTM=datename(year,@pDate)+'-01-01'
    SET @endYTM=dateadd(day,-1,dateadd(month,1,datename(year,@pDate)+'-'+datename(month,@pDate)+'-01'))


    --disinilah CTE beraksi

    ;WITH
    Sales(Product,SalesDate,Quantity) AS (
        SELECT * FROM #Sales
    ),
    SalesMonth(Product,MonthQuantity) AS (
        SELECT Product,sum(Quantity)
        FROM Sales a
        WHERE SalesDate BETWEEN @startMonth AND @endMonth
        GROUP BY Product
    ),
    SalesPrevMonth(Product,PrevMonthQuantity) AS (
        SELECT Product,sum(Quantity)
        FROM Sales a
        WHERE SalesDate BETWEEN @startPrevMonth AND @endPrevMonth
        GROUP BY Product
    ),
    SalesQTM(Product,QTMQuantity) AS (
        SELECT Product,sum(Quantity)
        FROM Sales a
        WHERE SalesDate BETWEEN @startQTM AND @endQTM
        GROUP BY Product
    ),
    SalesPrevQTM(Product,PrevQTMQuantity) AS (
        SELECT Product,sum(Quantity)
        FROM Sales a
        WHERE SalesDate BETWEEN @startPrevQTM AND @endPrevQTM
        GROUP BY Product
    ),
    SalesYTM(Product,YTMQuantity) AS (
        SELECT Product,sum(Quantity)
        FROM Sales a
        WHERE SalesDate BETWEEN @startYTM AND @endYTM
        GROUP BY Product
    ),
    Result(Product,MonthQuantity,PrevMonthQuantity,QTMQuantity,PrevQTMQuantity,YTMQuantity) AS (
        SELECT a.Product,
        b.MonthQuantity,c.PrevMonthQuantity,d.QTMQuantity,e.PrevQTMQuantity,f.YTMQuantity
        FROM (SELECT DISTINCT Product FROM Sales) a
            LEFT JOIN SalesMonth b ON a.Product=b.Product
            LEFT JOIN SalesPrevMonth c ON a.Product=c.Product
            LEFT JOIN SalesQTM d ON a.Product=d.Product
            LEFT JOIN SalesPrevQTM e ON a.Product=e.Product
            LEFT JOIN SalesYTM f ON a.Product=f.Product
    )

    SELECT * FROM Result

    Output: Output

     

     

     

     

    Gmn? Bingung kan Big Smile ... Intinya adalah CTE disini berfungsi seperti temporary table, hanya saja kita lebih mudah untuk membaca querynya karena code relatif lebih sedikit dibandingkan dengan menggunakan temporary table dengan mendeklarasikannya terlebih dahulu. Coba anda bayangkan jika SalesMonth,SalesPrevMonth,SalesQTM,SalesPrevQTM,dan Sales YTM dibuat menggunakan temporary variabel, untuk membuat coding mudah terbaca anda pasti membutuhkan lebih dari 2x jumlah baris code jika anda tidak menggunakan CTE. Inilah mengapa saya *** CTE karena banyak kasus yang jauh lebih rumit dari yang ini dapat diselesaikan dengan coding yang sedikit dan mudah dibaca.

    Posted Apr 18 2009, 06:40 AM by cahyo with 1 comment(s)
    Filed under:
  • Date Script Collections

    Seringkali saya menghadapi kasus pembuatan report untuk menampilkan data 1 bulan , 1 kuarter atau 1 tahun dan berbagai macam variasinya. Untuk menyelesaikannya diperlukan script untuk mendapatkan range tanggal sesuai dengan periode yang diminta. Beberapa baris script di bawah ini adalah beberapa koleksi saya ketika membuat report menggunakan periode-periode tersebut.

    DECLARE @pDate datetime
    SET @pDate='20090417'

    DECLARE @startMonth datetime,@endMonth datetime,@startPrevMonth datetime,@endPrevMonth datetime,@startNextMonth datetime,@endNextMonth datetime,
        @startQTM datetime,@endQTM datetime,@startPrevQTM datetime,@endPrevQTM datetime,
        @startYTM datetime,@endYTM datetime,@startPrevYTM datetime,@endPrevYTM datetime,@startPrevMoY datetime,@endPrevMoY datetime;

    SET @startMonth=datename(year,@pDate)+'-'+datename(month,@pDate)+'-01'
    SET @endMonth=dateadd(day,-1,dateadd(month,1,@startMonth))
    SET @startPrevMonth=datename(year,dateadd(month,-1,@pDate))+'-'+datename(month,dateadd(month,-1,@pDate))+'-01'
    SET @endPrevMonth=dateadd(day,-1,@startMonth)
    SET @startNextMonth=dateadd(month,1,@startMonth)
    SET @endNextMonth=dateadd(day,-1,dateadd(month,1,@startNextMonth))

    SET @startQTM=datename(year,@pDate)+'-'+cast(((datepart(month,@pDate)-1)/3)*3+1 AS varchar(2))+'-01'
    SET @endQTM=dateadd(day,-1,dateadd(month,1,datename(year,@pDate)+'-'+datename(month,@pDate)+'-01'))
    SET @startPrevQTM=datename(year,dateadd(month,-3,@pDate))+'-'+cast(((datepart(month,dateadd(month,-3,@pDate))-1)/3)*3+1 AS varchar(2))+'-01'
    SET @endPrevQTM=dateadd(day,-1,dateadd(month,1,datename(year,dateadd(month,-3,@pDate))+'-'+datename(month,dateadd(month,-3,@pDate))+'-01'))

    SET @startYTM=datename(year,@pDate)+'-01-01'
    SET @endYTM=dateadd(day,-1,dateadd(month,1,datename(year,@pDate)+'-'+datename(month,@pDate)+'-01'))
    SET @startPrevYTM=datename(year,dateadd(year,-1,@pDate))+'-01-01'
    SET @endPrevYTM=dateadd(day,-1,dateadd(month,1,datename(year,dateadd(year,-1,@pDate))+'-'+datename(month,dateadd(year,-1,@pDate))+'-01'))
    SET @startPrevMoY=dateadd(year,-1,@startMonth)
    SET @endPrevMoY=dateadd(day,-1,dateadd(month,1,@startPrevMoY))

     

    Keterangan:

    - @startMonth,@endMonth ==> untuk mendapatkan range tanggal 1 bulan

    - @start[Prev|Next]Month,@end[Prev|Next]Month ==> untuk mendapatkan range tanggal bulan sebelum/berikutnya

    - @startQTM,@endQTM,@startPrevQTM,@endPrevQTM ==> untuk mendapatkan range tanggal awal kuarter ini/sebelumnya sampai tanggal terakhir bulan. Contoh : jika @pDate='20090523' maka @startQTM='20090401' dan @endQTM='20090531'

    - @startYTM,@endYTM,@startPrevYTM,@endPrevYTM ==> untuk mendapatkan range tanggal awal tahun ini/sebelumnya sampai tanggal terakhir bulan. Contoh : jika @pDate='20090523' maka @startYTM='20090101' dan @endYTM='20090531'

     - @startPrevMoY,@endPrevMoY ==> untuk mendapatkan range tanggal bulan yang sama pada tahun sebelumnya.

More Posts
Powered by Community Server (Commercial Edition), by Telligent Systems