LEFT JOIN and WHERE clause are OK?

  • Hi there,

    For a calendar application: I have a table with "blocked times", in which I store on what DOW (day of week) a person is unavailable. In this routine, I supply a startdate and a number of days, returned is a rowset on which days, which times are blocked.

    In the example below I want to see what times are blocked, starting on January 4th 2009, and then 7 days ahead. In the table @blocks I add a number of blocked times.

    I works, still I got two questions:

    1)

    I use the code

    LEFT JOIN @blocks b ON 1=1

    It looks kind of weird.... is there a "better" way to write this?

    2)

    I would like to have a WHERE clause like this:

    WHERE blockFrom IS NOT NULL

    But that gives an error (Invalid column name 'blockFrom') so I have to put the whole calculation in the WHERE clause. Can this be done differntly?

    Thanks!

    Ray

    SET DATEFORMAT dmy

    DECLARE @startDate DATETIME

    SET @startDate = CAST('04-01-2009' AS DATETIME)

    DECLARE @numberOfDays TINYINT

    SET @numberOfDays = 7

    DECLARE@blocks TABLE (

    dayOfWeekTINYINT,

    startTimeCHAR(5),

    stopTimeCHAR(5)

    )

    INSERT INTO @blocks VALUES (1,'00:00','23:59')

    INSERT INTO @blocks VALUES (2,'00:00','09:00')

    INSERT INTO @blocks VALUES (2,'17:15','23:59')

    INSERT INTO @blocks VALUES (3,'00:00','09:00')

    INSERT INTO @blocks VALUES (3,'17:15','23:59')

    INSERT INTO @blocks VALUES (4,'00:00','09:00')

    INSERT INTO @blocks VALUES (4,'17:00','23:59')

    INSERT INTO @blocks VALUES (5,'00:00','09:00')

    INSERT INTO @blocks VALUES (5,'17:00','23:59')

    INSERT INTO @blocks VALUES (6,'00:00','09:00')

    INSERT INTO @blocks VALUES (6,'17:00','23:59')

    INSERT INTO @blocks VALUES (7,'00:00','23:59')

    SELECT t.calenderDate,

    CASE WHEN DATEPART(dw,t.calenderDate) = b.dayOfWeek

    THEN DATEADD(mi,CAST(RIGHT(startTime,2) AS INTEGER),DATEADD(hh,CAST(LEFT(startTime,2) AS INTEGER),t.calenderDate))

    ELSE NULL END AS blockFrom,

    CASE WHEN DATEPART(dw,t.calenderDate) = b.dayOfWeek

    THEN DATEADD(mi,CAST(RIGHT(stopTime,2) AS INTEGER),DATEADD(hh,CAST(LEFT(stopTime,2) AS INTEGER),t.calenderDate))

    ELSE NULL END AS blockTo

    FROM

    (

    SELECT DATEADD(d,v.number,@startDate) AS calenderDate

    FROM master..spt_values v

    WHERE v.type='P' AND v.number>=0 AND v.number<@numberOfDays

    ) AS t

    LEFT JOIN @blocks b ON 1=1

    WHERE CASE WHEN DATEPART(dw,t.calenderDate) = b.dayOfWeek

    THEN DATEADD(mi,CAST(RIGHT(startTime,2) AS INTEGER),DATEADD(hh,CAST(LEFT(startTime,2) AS INTEGER),t.calenderDate))

    ELSE NULL END IS NOT NULL

    ORDER BY t.calenderDate,b.startTime,b.stopTime

  • Instead of that CASE in WHERE clause, you could write this:

    SELECT t.calenderDate,

    CASE WHEN DATEPART(dw,t.calenderDate) = b.dayOfWeek

    THEN DATEADD(mi,CAST(RIGHT(startTime,2) AS INTEGER),DATEADD(hh,CAST(LEFT(startTime,2) AS INTEGER),t.calenderDate))

    ELSE NULL END AS blockFrom,

    CASE WHEN DATEPART(dw,t.calenderDate) = b.dayOfWeek

    THEN DATEADD(mi,CAST(RIGHT(stopTime,2) AS INTEGER),DATEADD(hh,CAST(LEFT(stopTime,2) AS INTEGER),t.calenderDate))

    ELSE NULL END AS blockTo

    FROM

    (

    SELECT DATEADD(d,v.number,@startDate) AS calenderDate

    FROM master..spt_values v

    WHERE v.type='P' AND v.number>=0 AND v.number<@numberOfDays) AS t

    LEFT JOIN @blocks b ON 1=1

    WHERE 1 = 1

    AND DATEPART(dw,t.calenderDate) = b.dayOfWeek

    AND DATEADD(mi,CAST(RIGHT(startTime,2) AS INTEGER),DATEADD(hh,CAST(LEFT(startTime,2) AS INTEGER),t.calenderDate)) IS NOT NULL

    ORDER BY t.calenderDate,b.startTime,b.stopTime

  • And also, LEFT JOIN is not required here. You can just write it as:

    SELECT t.calenderDate,

    CASE WHEN DATEPART(dw,t.calenderDate) = b.dayOfWeek

    THEN DATEADD(mi,CAST(RIGHT(startTime,2) AS INTEGER),DATEADD(hh,CAST(LEFT(startTime,2) AS INTEGER),t.calenderDate))

    ELSE NULL END AS blockFrom,

    CASE WHEN DATEPART(dw,t.calenderDate) = b.dayOfWeek

    THEN DATEADD(mi,CAST(RIGHT(stopTime,2) AS INTEGER),DATEADD(hh,CAST(LEFT(stopTime,2) AS INTEGER),t.calenderDate))

    ELSE NULL END AS blockTo

    FROM

    (

    SELECT DATEADD(d,v.number,@startDate) AS calenderDate

    FROM master..spt_values v

    WHERE v.type='P' AND v.number>=0 AND v.number<@numberOfDays) AS t,

    @blocks b

    WHERE 1 = 1

    AND DATEPART(dw,t.calenderDate) = b.dayOfWeek

    AND DATEADD(mi,CAST(RIGHT(startTime,2) AS INTEGER),DATEADD(hh,CAST(LEFT(startTime,2) AS INTEGER),t.calenderDate)) IS NOT NULL

    ORDER BY t.calenderDate,b.startTime,b.stopTime

  • gyessql (1/10/2009)


    And also, LEFT JOIN is not required here. You can just write it as:

    SELECT ...

    FROM (...) AS t, @blocks b

    ...

    You would be better off sticking with the newer JOIN syntax:

    SELECT ...

    FROM (...) AS t CROSS JOIN @blocks b

    ...

    [font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
    Proactive Performance Solutions, Inc.
    [/font]
    [font="Verdana"] "Performance is our middle name."[/font]

  • RBarryYoung (1/10/2009)


    You would be better off sticking with the newer JOIN syntax:

    SELECT ...

    FROM (...) AS t CROSS JOIN @blocks b

    ...

    SELECT ...

    FROM (...) AS t, @blocks b

    ...

    Is there any performance difference by using CROSS JOIN than just taking the table in the FROM clause?

  • Not that I know of.

    [font="Times New Roman"]-- RBarryYoung[/font], [font="Times New Roman"] (302)375-0451[/font] blog: MovingSQL.com, Twitter: @RBarryYoung[font="Arial Black"]
    Proactive Performance Solutions, Inc.
    [/font]
    [font="Verdana"] "Performance is our middle name."[/font]

  • Hey folks,

    Thanks for all your replies. I think that using CROSS JOIN is the best, because it's a newer syntax.

    Thx,

    Ray

Viewing 7 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic. Login to reply