January 2008 - Posts

Utterly amazing; we opened registrations at 7.45pm and as of now 22 hours later we have 317 places booked.

We have worked with the venue today based on the volume of registrations and have increased our potential numbers to a maximum of 420.

So, if you've not already booked and intend coming then do it NOW.

http://www.sqlserverfaq.com/sqlbits

For the press release: http://www.sqlserverfaq.com/sqlbits/sqlbits2008registrations.html

Tony.

 

Registration is now open for SQLBits 2008 March event.

Come and join us at the Lakeside Conference Centre in Birmingham for SQLBits (the sql); believe me the sessions are way better than the punch line! We have kept costs low with help from our sponsors, so low in fact it's free to attend again.

20 technical Sessions broken up into 4 tracks covering all areas a SQL Pro is interested in and on top of that a recruitment panel and new product demonstrations - something for everybody - Development, DBA, Business Intelligence and of course SQL Server 2008. Check out the confirmed sessions.

Technical Sessions end at 5pm but the day continues first with a Recruitment panel and New production demos and then into an informal networking and social evening at our Group By drinks reception - a great opportunity to relax and chat about our holidays, hobbies, ok - get real - more SQL!

Register quickly; we ran out of places in 8 days at the October 2007 event.

Register Me For SQLBits 2008

Technical Session List:

SQL Server 2008
Making more of SSIS in 2008
Reporting in SQL Server 2008
SQL Server 2008 � Declarative Management Framework concepts & database problem solutions with policy management.
Where do you live? Intro to spatial indexing
SQL Server 2008 TSQL Enhancements

Business Intelligence
Using Analysis Services as a data source for Reporting Services reports
Extending SSIS with custom Data Flow components
Master Data Management (MDM)

DBA

SQL Server High Availability and Disaster Recovery Overview
What Are You Waiting For?
I/O! I/O! It�s off to disk we go...
Introduction to SQL 2008 Performance Data Collector
"SELECT TOP(@x) Name FROM MyFavouriteDMVs ORDER BY MyRanking"
Administering SQL Server 2008 and 2005 with Windows PowerShell

Developer
Transient data in SQL Server
Getting to grips with Service Broker.
2005 SQLCMD Scripting
Understanding LINQ in .NET Framework V3.5 and Beyond
Development Life Cycle using Visual Studio Team Edition for DB Professionals
Making the leap into Advanced SQL

Regards
SQL Bits Organising Committee
.

A collegue raised a good question today, why does using BETWEEN '2007-01-01' and '2007-12-31 23:59:59' return rows that are in the year 2008 and using BETWEEN '2007-01-01' and '2007-12-31 23:59:29' not?

The accuracy of smalldatetime is to the minute so when specifying seconds SQL Server will round up or round down to the nearest minute...

print cast(  '2007-12-31 23:59:29'  as datetime )

print cast(  '2007-12-31 23:59:29'  as smalldatetime )

 

Dec 31 2007 11:59PM

Dec 31 2007 11:59PM

 

print cast(  '2007-12-31 23:59:30'  as datetime )

print cast(  '2007-12-31 23:59:30'  as smalldatetime )


Dec 31 2007 11:59PM

Jan  1 2008 12:00AM

If you use DATEPART( second on the casted date you will see that on casting to smalldatetime you will get 0.

smalldatetime is often used when you are storing only the date portion or you are not interesting in seconds, this is to save space more than anything else.

When you query columns that are definied as smalldatetime for instance....

select * from trades where trade_date between '20070101' and '2007-12-31T23:59:59'

You need to make sure you don't specify the seconds otherwise SQL Server will round your input so the above query will actually become...

select * from trades where trade_date between '20070101' and '2008-01-01T00:00:00'

It's probably safer to use >= and < for instance...

select * from trades where trade_date >= '20070101' trade_date < '2008-01-01'

Another aspect - make sure you specify date literals without the hypens! If somebody changes your default langauge to British then '2007-10-01' will actually become 1st January 2007 and not 10th October 2007.

Want a calendar table? Here’s the one I tend to use and an example at the bottom of how to summarise using it.

It can be expanded if you are interested in working / non working days; it’s basically just dropping down at day level and have a column to indicate a working / non working day.

Another method I use when summarising to month level is SUM( CASE <exp> ) but that’s another article that no doubt will show up on here in the coming weeks J.

There is one glaring problem with this and it’s because of SQL Server’s datetime precision, i.e. it’s only precise to 300th millisecond so the end of my day is 23:59:59.997.

{Modified on 21st Jan 2008 to include ISO week and SQL Server week numbers (starting 1 jan).

create table calendar (

    calendar_id             int not null identity constraint pk_calendar primary key clustered,

    period_start            datetime    not null,

    period_end              as cast( left( convert( varchar(60),

                 dateadd( day, -1, case period_type

                                        when 'WY' then dateadd( week, 1, period_start )

                                        when 'WI' then dateadd( week, 1, period_start )

                                        when 'M' then dateadd( month, 1, period_start )

                                        when 'Q' then dateadd( month, 3, period_start )

                                        when 'H' then dateadd( month, 6, period_start )

                                        when 'Y' then dateadd( year, 1, period_start )

                                   end ), 121 ), 10 ) + 'T23:59:59.997' as datetime ),  

    period_name             varchar(50) not null,

    period_type             varchar(2)  not null    check( period_type in ( 'WY', 'WI', 'M', 'Q', 'H', 'Y' ) ),

        constraint uk_calendar_period_start_type unique( period_start, period_type ),

        constraint uk_calendar_period_name unique( period_name, period_type )

)

go

/***

    period_type

        WY - Week in Year according to SQL Server; WI - Week in Year according to ISO

        M  - Month

        Q  - Quarter

        H  - Half

        Y  - Year

 

***/

 

 

--  Populate the calendar (month based stuff first; that is periods are aligned with start of month)

declare @start_date datetime

declare @date datetime

set @start_date = '20060101'

set @date = @start_date

 

set nocount on

 

while @date <= dateadd( year, 1, current_timestamp )

begin

    insert calendar( period_start, period_name, period_type )

        values( @date, left( datename( month, @date ), 3 ) + '-' + datename( year, @date ), 'M' )

 

    if datepart( month, @date ) in ( 1, 4, 7, 10 )

        insert calendar( period_start, period_name, period_type )

            values( @date, 'Q' + case datepart( month, @date )

                                    when 1 then '1'

                                    when 4 then '2'

                                    when 7 then '3'

                                    when 10 then '4'

                                 end + '-' + datename( year, @date ), 'Q' )

 

    if datepart( month, @date ) in ( 1, 7 )

        insert calendar( period_start, period_name, period_type )

            values( @date, 'H' + case datepart( month, @date )

                                    when 1 then '1'

                                    when 7 then '2'

                                 end + '-' + datename( year, @date ), 'H' )

 

    if datepart( month, @date ) = 1

        insert calendar( period_start, period_name, period_type )

            values( @date, 'Y' + datename( year, @date ), 'Y' )

           

    set @date = dateadd( month, 1, @date )

 

end

go

 

 

--  First we need something to give us our ISO week number

create function dbo.fn_iso_week_number(

    @date datetime )

returns int

as

begin

/***

 

    The code here is from the article http://www.sqlservercentral.com/articles/Advanced+Querying/onthetrailoftheisoweek/1675/ by Christoffer Hedgate 20 Jan 2005.

    Note, change 01-04 in Christoffer's article because dates need to be passed as YYYYMMDD in SQL Server to avoid any inconsistency.

 

****/

 

    return( CASE

 

     -- Exception where @date is part of week 52 (or 53) of the previous year

     WHEN @date < CASE (DATEPART(dw, CAST(YEAR(@date) AS CHAR(4)) + '0104') + @@DATEFIRST - 1) % 7

      WHEN 1 THEN CAST(YEAR(@date) AS CHAR(4)) + '0104'

      WHEN 2 THEN DATEADD(d, -1, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      WHEN 3 THEN DATEADD(d, -2, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      WHEN 4 THEN DATEADD(d, -3, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      WHEN 5 THEN DATEADD(d, -4, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      WHEN 6 THEN DATEADD(d, -5, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      ELSE DATEADD(d, -6, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      END

     THEN

      (DATEDIFF(d,

       CASE (DATEPART(dw, CAST(YEAR(@date) - 1 AS CHAR(4)) + '0104') + @@DATEFIRST - 1) % 7

       WHEN 1 THEN CAST(YEAR(@date) - 1 AS CHAR(4)) + '0104'

       WHEN 2 THEN DATEADD(d, -1, CAST(YEAR(@date) - 1 AS CHAR(4)) + '0104')

       WHEN 3 THEN DATEADD(d, -2, CAST(YEAR(@date) - 1 AS CHAR(4)) + '0104')

       WHEN 4 THEN DATEADD(d, -3, CAST(YEAR(@date) - 1 AS CHAR(4)) + '0104')

       WHEN 5 THEN DATEADD(d, -4, CAST(YEAR(@date) - 1 AS CHAR(4)) + '0104')

       WHEN 6 THEN DATEADD(d, -5, CAST(YEAR(@date) - 1 AS CHAR(4)) + '0104')

       ELSE DATEADD(d, -6, CAST(YEAR(@date) - 1 AS CHAR(4)) + '0104')

       END,

       @date

      ) / 7) + 1

 

     -- Exception where @date is part of week 1 of the following year

     WHEN @date >= CASE (DATEPART(dw, CAST(YEAR(@date) + 1 AS CHAR(4)) + '0104') + @@DATEFIRST - 1) % 7

      WHEN 1 THEN CAST(YEAR(@date) + 1 AS CHAR(4)) + '0104'

      WHEN 2 THEN DATEADD(d, -1, CAST(YEAR(@date) + 1 AS CHAR(4)) + '0104')

      WHEN 3 THEN DATEADD(d, -2, CAST(YEAR(@date) + 1 AS CHAR(4)) + '0104')

      WHEN 4 THEN DATEADD(d, -3, CAST(YEAR(@date) + 1 AS CHAR(4)) + '0104')

      WHEN 5 THEN DATEADD(d, -4, CAST(YEAR(@date) + 1 AS CHAR(4)) + '0104')

      WHEN 6 THEN DATEADD(d, -5, CAST(YEAR(@date) + 1 AS CHAR(4)) + '0104')

      ELSE DATEADD(d, -6, CAST(YEAR(@date) + 1 AS CHAR(4)) + '0104')

      END

     THEN 1

 

     ELSE

      -- Calculate the ISO week number for all dates that are not part of the exceptions above

      (DATEDIFF(d,

      CASE (DATEPART(dw, CAST(YEAR(@date) AS CHAR(4)) + '0104') + @@DATEFIRST - 1) % 7

      WHEN 1 THEN CAST(YEAR(@date) AS CHAR(4)) + '0104'

      WHEN 2 THEN DATEADD(d, -1, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      WHEN 3 THEN DATEADD(d, -2, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      WHEN 4 THEN DATEADD(d, -3, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      WHEN 5 THEN DATEADD(d, -4, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      WHEN 6 THEN DATEADD(d, -5, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      ELSE DATEADD(d, -6, CAST(YEAR(@date) AS CHAR(4)) + '0104')

      END,

      @date

      ) / 7) + 1

     END

    )

end
go

 

--  Insert Week in Year and ISO Week rows

declare @start_date datetime

declare @date datetime

set @start_date = '20060101'

set @date = @start_date

 

set nocount on

 

while @date <= dateadd( year, 1, current_timestamp )

begin

    insert calendar( period_start, period_name, period_type )

        values( @date, datename( year, dateadd( year, case when datepart( month, @date ) = 1 and dbo.fn_iso_week_number( @date ) > 50 then -1 else 0 end, @date ) ) + '-W' + right( '0' + cast( dbo.fn_iso_week_number( @date ) as varchar(2) ), 2 ), 'WI' )

 

    insert calendar( period_start, period_name, period_type )

        values( @date, datename( year, @date ) + '-W' + right( '0' + cast( datepart( week, @date ) as varchar(2) ), 2 ), 'WY' )

 

    set @date = dateadd( week, 1, @date )