Getting Started with Adobe After Effects - Part 6: Motion Blur
First Time? You can support us by signing up. It takes only 5 seconds. Click here to sign up. If you already have an account, click here to login.
Loading

SQLServer Quiz 2010 - CASE function, including COALESCE, data types, and multiple query executions description

  • 1.What is the data type of the result of a CASE function?.

    2.Can you use the CASE function to simulate dynamic ORDER BY clause? If yes, how?.

    3.Demonstrate how you can use the APPLY operator or a subquery to avoid executing same query multiple times when the query (including shredding an xml doc) is part of the CASE function.

    Posted on 10-14-2010 00:00 |
    Alejandro Mesa
    266 · 1% · 164

16  Answers  

Subscribe to Notifications
Previous 1 | 2 Next
  • Score
    8

    Q.) What is the data type of the result of a CASE function?.

    A.) Returns the highest precedence type from the set of types in resultexpressions and the optional elseresult_expression.

    Q.)Can you use the CASE function to simulate dynamic ORDER BY clause? If yes, how?.

    A.) Yes.

    SELECT EmpID,IsFullTime FROM tblEmployee
    ORDER BY 
        CASE IsFullTime WHEN 1 THEN EmpID END DESC
            ,CASE WHEN IsFullTime = 0 THEN EmpID END
    

    Q.)Demonstrate how you can use the APPLY operator or a subquery to avoid executing same query multiple times when the query (including shredding an xml doc) is part of the CASE function.

    A.) Good example is given here. http://www.projectdmx.com/tsql/rowconcatenate.aspx

    Replied on Oct 14 2010 1:39AM  . 
    Ritesh Shah
    75 · 2% · 747
  • Score
    9

    1.The datatype of the case statement will be the datatype which is having the highest precedence used in all datattypes among all the branches of the case statement. Supopse, a case statement has 2 conditions, one is of integer datatype and another is of real datatype, as real datatype has highest precendence over Int, Result will be real datatype.

    This will gives the order of precedence of datatypes.

    http://msdn.microsoft.com/en-us/library/ms190309.aspx

    2.These are 2 queries taken which will show dynamic order by clause.

    SELECT BusinessEntityID, SalariedFlag
    FROM HumanResources.Employee
    ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
            ,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;
    
    SELECT BusinessEntityID, LastName, TerritoryName, CountryRegionName
    FROM Sales.vSalesPerson
    WHERE TerritoryName IS NOT NULL
    ORDER BY CASE CountryRegionName WHEN 'United States' THEN TerritoryName
             ELSE CountryRegionName END;
    

    These 2 queries are from MSDN :)

    3.2nd query in below example will show how we can avoid Executing same expression multiple times by using cross apply. How ever i didn't understand the word why u used "shredding an xmldoc"?? Is it related with question??

    declare @t table
    (
        Id int
    )
    insert into @t values (1),(2),(3),(4),(5),(6)
    
    select ID,
    case
        when ID % 2 = 0 and ID % 3 = 0 then 'Divides by both 2 & 3'
        when ID % 2 = 0  then 'Divides by 2 only'
        when ID % 3 = 0 then 'Divides by 3 only'
        else 'Not divide by 2 or 2'
    end
     from @t
    
     select ID,
    case
        when t1.divide2 = 0 and t1.divide3 = 0 then 'Divides by both 2 & 3'
        when t1.divide2 = 0  then 'Divides by 2 only'
        when t1.divide3 = 0 then 'Divides by 3 only'
        else 'Not divide by 2 or 3'
    end
     from @t 
     cross apply (select ID % 2 as divide2, ID % 3 as divide3  )t1
    
    Replied on Oct 14 2010 1:49AM  . 
    Ramireddy
    2 · 41% · 12972
  • Score
    8

    1) Case statement always return highest precedence

    http://blog.sqlauthority.com/2010/10/08/sql-server-simple-explanation-of-data-type-precedence/

    2)

    USE AdventureWorks
    GO
    DECLARE @OrderBy VARCHAR(10)
    DECLARE @OrderByDirection VARCHAR(1)
    SET @OrderBy = 'State' ----Other options Postal for PostalCode,
    ---- State for StateProvinceID, City for City
    SET @OrderByDirection = 'D' ----Other options A for ascending,
    ---- D for descending
    SELECT AddressID, City, StateProvinceID, PostalCode
    FROM person.address
    WHERE AddressID < 100
    ORDER BY
    CASE WHEN @OrderBy = 'Postal'
    AND @OrderByDirection = 'D'
    THEN PostalCode END DESC,
    CASE WHEN @OrderBy = 'Postal'
    AND @OrderByDirection != 'D'
    THEN PostalCode END,
    CASE WHEN @OrderBy = 'State'
    AND @OrderByDirection = 'D'
    THEN StateProvinceID END DESC,
    CASE WHEN @OrderBy = 'State'
    AND @OrderByDirection != 'D'
    THEN StateProvinceID END,
    CASE WHEN @OrderBy = 'City'
    AND @OrderByDirection = 'D'
    THEN City END DESC,
    CASE WHEN @OrderBy = 'City'
    AND @OrderByDirection != 'D'
    THEN City END
    GO
    

    3) RamiReddy has got it right. I can not come up anything better.

    Replied on Oct 14 2010 9:51AM  . 
    Nupur Dave
    172 · 1% · 284
  • Score
    8

    1.What is the data type of the result of a CASE function?.

    Returns the highest precedence type from the set of types in resultexpressions and the optional elseresult_expression ( Taken from MSDN).

    2.Can you use the CASE function to simulate dynamic ORDER BY clause? If yes, how?.

    --( Taken from MSDN).

    SELECT BusinessEntityID, SalariedFlag
    
    FROM HumanResources.Employee
    
    ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
    
            ,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;
    
    GO
    

    3.Demonstrate how you can use the APPLY operator or a subquery to avoid executing same query multiple times when the query (including shredding an xml doc) is part of the CASE function.

    Replied on Oct 14 2010 11:19AM  . 
    rpathak
    299 · 0% · 145
  • Score
    8

    What is the data type of the result of a CASE function?

    The data type will be based on the highest precedence of the resulting data type of both, the WHEN and the ELSE section. (SQL 2005: http://msdn.microsoft.com/en-us/library/ms190309%28v=SQL.90%29.aspx)

    Can you use the CASE function to simulate dynamic ORDER BY clause?

    Yes.

    If yes, how?

    There are several options including the ones already presented.

    Here's another version using a variable to change the sort order (source: http://www.sqlteam.com/article/dynamic-order-by):

    (Side note: the sample below requires to have data types for CompanyName, ContactName, and ContactTitle that are similar or can be implicit converted into the one with the highes precedence. See question 1.)

    DECLARE @SortOrder tinyint
    SET @SortOrder = 2
    SELECT CompanyName,
        ContactName,
        ContactTitle
    FROM Customers
    ORDER BY CASE WHEN @SortOrder = 1 THEN CompanyName
        WHEN @SortOrder = 2 THEN ContactName
        ELSE ContactTitle
    END
    

    Demonstrate how you can use the APPLY operator or a subquery to avoid executing same query multiple times when the query (including shredding an xml doc) is part of the CASE function.

    Like some of the previous posters, I'm having difficulties to understand the question. If you're not looking for an answer along the lines Ramireddy came up with, please provide more information.

    Replied on Oct 14 2010 5:27PM  . 
    lmu92
    0 · 0% · 0
  • Score
    9

    What is the data type of the result of a CASE function?

    Returns the highest precedence type from the set of types of results (including ELSE result).

    Can you use the CASE function to simulate dynamic ORDER BY clause? If yes, how?

    Yes, and the following example demonstrate how:

    DECLARE @sort_direction BIT = 0; /* 0 for ascending order, or 1 for descending order.*/
    DECLARE @sort_column TINYINT = 0; /* 0 for num column. If not then string column.*/
    
    SELECT num, string
      FROM (VALUES(1, 'z'), (2, 'y'), (3, 'x')) AS T(num, string)
     ORDER BY CASE WHEN @sort_direction = 0
                        THEN CASE WHEN @sort_column = 0
                                       THEN RIGHT(REPLICATE('0', 38) + CAST(num AS VARCHAR(38)), 38)
                                  ELSE string
                             END
              END,
              CASE WHEN @sort_direction = 1
                        THEN CASE WHEN @sort_column = 0
                                       THEN RIGHT(REPLICATE('0', 38) + CAST(num AS VARCHAR(38)), 38)
                             ELSE string
                        END
              END DESC
    

    Demonstrate how you can use the APPLY operator or a subquery to avoid executing same query multiple times when the query (including shredding an xml doc) is part of the CASE function.

    The following script demonstrate how using subquery or APPLY operator avoided multiple execution of the COUNT query:

    SELECT CASE (SELECT COUNT(N) AS num_count
                   FROM tsqlc_Tally) % 2
                WHEN 0 THEN 'Even'
                ELSE 'Odd'
           END AS odd_or_even;
    
    --subquery
    SELECT CASE num_count % 2
                WHEN 0 THEN 'Even'
                ELSE 'Odd'
           END AS odd_or_even
      FROM (SELECT COUNT(N) AS num_count
              FROM tsqlc_Tally) AS T;
    
    --APPLY operator
    SELECT odd_or_even
      FROM (SELECT COUNT(N) AS num_count
              FROM tsqlc_Tally) AS T
            CROSS APPLY
            (SELECT CASE num_count % 2
                         WHEN 0 THEN 'Even'
                         ELSE 'Odd'
                    END AS odd_or_even) AS T2;
    

    See execution plans to confirm this, and the same principle applies for other queries like shredding an xml doc, and the following example demonstrate this:

    SELECT CASE ISDATE(x.value('(/daterow/datecol)[1]', 'nvarchar(max)'))
                WHEN 0 THEN CAST('20100101' AS DATE)
                ELSE x.value('(/daterow/datecol)[1]', 'date')
           END
      FROM (SELECT CAST('<daterow><datecol>20101016</datecol></daterow>' AS xml)) AS T(x)
    
    --subquery
    SELECT CASE ISDATE(x)
                WHEN 0 THEN CAST('20100101' AS DATE)
                ELSE CAST(x AS DATE)
           END
      FROM (SELECT x.value('(/daterow/datecol)[1]', 'nvarchar(max)')
              FROM (SELECT CAST('<daterow><datecol>20101016</datecol></daterow>' AS xml)) AS T(x)) AS T(x)
    
    Replied on Oct 15 2010 8:41PM  . 
    Muhammad Al Pasha
    27 · 6% · 1920
  • Score
    9

    1.When you use CASE function in a query, the result will be the expression with the highest precedence. So, it's a good practice to always use the same type of expressions when using CASE function. You may want to read this blog SQL Server Case/When Data Type problems

    2.Yes, case function can be used to simulate dynamic Order By. Say, you pass @OrderBy clause to the stored procedure and @OrderBy can be either 'OrderDate' or 'TotalDue'

    Example:

    declare @OrderBy varchar(20) 
    
    set @OrderBy = 'TotalDue'
    
    select top (10)  OrderDate, TotalDue
    from AdventureWorks.Sales.SalesOrderHeader 
    ORDER BY case when @OrderBy = 'TotalDue' then TotalDue end,
    case when @OrderBy = 'OrderDate' then OrderDate end
    
    set @OrderBy  = 'OrderDate'
    
    select top (10)  OrderDate, TotalDue
    from AdventureWorks.Sales.SalesOrderHeader 
    ORDER BY case when @OrderBy = 'TotalDue' then TotalDue end,
    case when @OrderBy = 'OrderDate' then OrderDate end
    

    3.APPLY operator can be used in many situations - one of the applications is to avoid the repeating of the same statements.

    Say, we want to find 10 most expensive products for each category of products but only if the word Silver is in one of the names of the products. Here is the query we can write (using APPLY operator and using this newly created column name in the WHERE expression):

    Select PC.[Name] as Category, 
    PSC.[Name] as SubCategory,  stuff(F.[Products],1,1,'') as [Products]
    from AdventureWorks.Production.ProductCategory PC
    inner join 
    AdventureWorks.Production.ProductSubcategory PSC on PC.ProductCategoryID = PSC.ProductSubcategoryID 
    cross apply (select top (10) '|' + [Name] from AdventureWorks.Production.Product P
    where P.ProductSubcategoryID = PSC.ProductSubcategoryID order by ListPrice DESC FOR XML PATH('') ) F (Products)
    where [Products] LIKE '%Silver%'
    

    Of course, there are many other applications of the APPLY operator, say, you can check one of them in my blog:

    Parsing the Address field to its individual components where I show how using multiple cross apply operators can reduce complexity of the task and solve it in a few steps.

    There is also a very deep blog about CASE and Subqueries by Craig Freedman Subqueries in CASE expressions.

    Here is an example of using APPLY operator to shred XML document:

    declare @xml XML = '<OrdersWithTheirCopies>
     <Order OrderID="1" OrderNumber="Order #1">
      <OrderLines>
       <OrderLine OrderLineID="1" LineNumber="Line #1" ItemDescription="pipe - 100" />
       <OrderLine OrderLineID="2" LineNumber="Line #2" ItemDescription="plate 10" />
       <OrderLine OrderLineID="3" LineNumber="Line #3" ItemDescription="glass 1 mm." />
      </OrderLines>
      <OrderCopies>
       <Copy CopyNumber="1" OrderHistoryID="3">
        <OrderLineHistory OrderLineID="1" OrderLineHistoryID="8" ItemDescription="pipe - 100" />
        <OrderLineHistory OrderLineID="2" OrderLineHistoryID="9" ItemDescription="plate 10" />
        <OrderLineHistory OrderLineID="3" OrderLineHistoryID="10" ItemDescription="glass 1 mm." />
       </Copy>
       <Copy CopyNumber="2" OrderHistoryID="4">
        <OrderLineHistory OrderLineID="1" OrderLineHistoryID="11" ItemDescription="pipe - 100" />
        <OrderLineHistory OrderLineID="2" OrderLineHistoryID="12" ItemDescription="plate 10" />
        <OrderLineHistory OrderLineID="3" OrderLineHistoryID="13" ItemDescription="glass 1 mm." />
       </Copy>
       <Copy CopyNumber="3" OrderHistoryID="6">
        <OrderLineHistory OrderLineID="1" OrderLineHistoryID="16" ItemDescription="pipe - 100" />
        <OrderLineHistory OrderLineID="2" OrderLineHistoryID="17" ItemDescription="plate 10" />
        <OrderLineHistory OrderLineID="3" OrderLineHistoryID="18" ItemDescription="glass 1 mm." />
       </Copy>
      </OrderCopies>
     </Order>
     <Order OrderID="2" OrderNumber="Order #2">
      <OrderLines>
       <OrderLine OrderLineID="4" LineNumber="Line #1" ItemDescription="pipe - 200" />
       <OrderLine OrderLineID="5" LineNumber="Line #2" ItemDescription="plate 20" />
      </OrderLines>
      <OrderCopies>
       <Copy CopyNumber="1" OrderHistoryID="2">
        <OrderLineHistory OrderLineID="4" OrderLineHistoryID="6" ItemDescription="pipe - 200" />
        <OrderLineHistory OrderLineID="5" OrderLineHistoryID="7" ItemDescription="plate 20" />
       </Copy>
       <Copy CopyNumber="2" OrderHistoryID="5">
        <OrderLineHistory OrderLineID="4" OrderLineHistoryID="14" ItemDescription="pipe - 200" />
        <OrderLineHistory OrderLineID="5" OrderLineHistoryID="15" ItemDescription="plate 20" />
       </Copy>
      </OrderCopies>
     </Order>
     <Order OrderID="3" OrderNumber="Order #3">
      <OrderLines>
       <OrderLine OrderLineID="6" LineNumber="Line #1" ItemDescription="pipe - 300" />
       <OrderLine OrderLineID="7" LineNumber="Line #2" ItemDescription="plate - 30" />
       <OrderLine OrderLineID="8" LineNumber="Line #3" ItemDescription="glass - 3 mm" />
       <OrderLine OrderLineID="9" LineNumber="Line #4" ItemDescription="pipe - 330" />
       <OrderLine OrderLineID="10" LineNumber="Line #5" ItemDescription="plate - 33" />
      </OrderLines>
      <OrderCopies>
       <Copy CopyNumber="1" OrderHistoryID="1">
        <OrderLineHistory OrderLineID="6" OrderLineHistoryID="1" ItemDescription="pipe - 300" />
        <OrderLineHistory OrderLineID="7" OrderLineHistoryID="2" ItemDescription="plate - 30" />
        <OrderLineHistory OrderLineID="8" OrderLineHistoryID="3" ItemDescription="glass - 3 mm" />
        <OrderLineHistory OrderLineID="9" OrderLineHistoryID="4" ItemDescription="pipe - 330" />
        <OrderLineHistory OrderLineID="10" OrderLineHistoryID="5" ItemDescription="plate - 33" />
       </Copy>
      </OrderCopies>
     </Order>
    </OrdersWithTheirCopies>'
    

    &

    SELECT
        O.x.value('@OrderID[1]', 'int') AS OrderID,
        O.x.value('@OrderNumber[1]', 'varchar(50)') AS OrderNumber
    FROM
        @xml.nodes('/OrdersWithTheirCopies/Order') AS O(x);
    
    SELECT
        C.x.value('@OrderHistoryID[1]', 'int') AS OrderHistoryID,
        O.x.value('@OrderID[1]', 'int') AS OrderID,
        C.x.value('@CopyNumber[1]', 'int') AS CopyNumber
    FROM
      @xml.nodes('/OrdersWithTheirCopies/Order') AS O(x)
      CROSS APPLY
      O.x.nodes('OrderCopies/Copy') AS C(x);
    
    SELECT
        L.x.value('@OrderLineHistoryID[1]', 'int') AS OrderLineHistoryID,
        O.x.value('@OrderID[1]', 'int') AS OrderID,
        L.x.value('@OrderLineID[1]', 'int') AS OrderLineID,
        L.x.value('@ItemDescription[1]', 'varchar(max)') AS ItemDescription
    FROM
      @xml.nodes('/OrdersWithTheirCopies/Order') AS O(x)
      CROSS APPLY
      O.x.nodes('OrderCopies/Copy') AS C(x)
      CROSS APPLY
      C.x.nodes('OrderLineHistory') AS L(x);
    
    Replied on Oct 17 2010 7:47AM  . 
    Naomi
    33 · 6% · 1774
  • Score
    8

    1)What is the data type of the result of a CASE function?.

    Returns the highest precedence type from the set of types in resultexpressions and the optional elseresult_expression

    Reference:

    CASE (Transact-SQL)

    Data Type Precedence (Transact-SQL)

    2) Can you use the CASE function to simulate dynamic ORDER BY clause?

    Yes

    If yes, how?.

    The following examples uses the CASE expression in an ORDER BY clause to determine the sort order of the rows based on a given column value. In the first example, the value in the SalariedFlag column of the HumanResources.Employee table is evaluated. Employees that have the SalariedFlag set to 1 are returned in order by the EmployeeID in descending order. Employees that have the SalariedFlag set to 0 are returned in order by the EmployeeID in ascending order.

    SELECT BusinessEntityID, SalariedFlag
    FROM HumanResources.Employee
    ORDER BY CASE SalariedFlag WHEN 1 THEN BusinessEntityID END DESC
            ,CASE WHEN SalariedFlag = 0 THEN BusinessEntityID END;
    GO
    

    In the second example, the result set is ordered by the column TerritoryName when the column CountryRegionName is equal to 'United States' and by CountryRegionName for all other rows.

    SELECT BusinessEntityID, LastName, TerritoryName, CountryRegionName
    FROM Sales.vSalesPerson
    WHERE TerritoryName IS NOT NULL
    ORDER BY 
    CASE CountryRegionName WHEN 'United States' THEN TerritoryName
             ELSE CountryRegionName END;
    

    Note: CASE can be used on UPDATE statement, SET statement, HAVING clause apart from ORDER by clause.

    Source: Using CASE in an ORDER BY clause http://msdn.microsoft.com/en-us/library/ms181765.aspx

    3) I could not understand the question.

    Replied on Oct 17 2010 7:55AM  . 
    Sivaprasad S - SIVA
    238 · 1% · 188
  • Score
    9

    1. What is the data type of the result of a CASE function?

    2.Can you use the CASE function to simulate dynamic ORDER BY clause? If yes, how?

    3.Demonstrate how you can use the APPLY operator or a subquery to avoid executing same query multiple times when the query (including shredding an xml doc) is part of the CASE function.

    1.The data type of the result of a CASE function depends on the output values specified. If all output values are of data type varchar for instance, then the result of the function will also be varchar. However if the data types within the function are mixed, for example "CASE WHEN 1=1 THEN 'x' ELSE N'y' END" then the data type with the highest precedence is returned, in this case nvarchar (even though this CASE function will never return the nvarchar output value). As a result of this, each output value must be valid for implicit conversion to the data type of the highest precedence within the CASE function, else an error will occur.

    2.The CASE function can be used in the ORDER BY clause, and therefore you can order the data depending on the conditions you set in the CASE function. The CASE function is resolved for each row in the result set, so your logic must affect each row in the correct way to produce the desired "dynamic" effect. For example:

    (checks a user parameter and orders by matching employee name(s) first, then all other employees alphabetically)

    ORDER BY
    
             CASE WHEN EmployeeName LIKE @myvar+'%' THEN 0 ELSE 1 END
    
            ,EmployeeName
    

    3.I presume this question is referring to a subquery within the SELECT list (as part of a CASE function), e.g.

    SELECT
                     EmployeeID
                    ,CASE WHEN       (SELECT fieldXML.exist('/Employee[@ID=sql:column("EmployeeID")][1]')
                                                                     FROM xmlfiles
                                                                     WHERE Employees.xmldocID = xmlfiles.xmldocID) = 1
                                    THEN     (SELECT fieldXML.value('/Employee[@ID=sql:column("EmployeeID")][1]/Name[1]','varchar(100)')
                                                                     FROM xmlfiles
                                                                     WHERE Employees.xmldocID = xmlfiles.xmldocID)
                                    ELSE '' END AS EmpName
    FROM Employees
    

    In the above example, the CASE function and therefore the subquery is executing for every row of the Employees table, and shredding the xml document to find each employee's name based on their ID, if the ID exists in the XML document.

    The multiple executions come from the SELECT statement being executed within the outer SELECT list. To reduce the executions, ideally down to one, we can move the inner SELECT statement(s) to become subqueries or part of an APPLY statement. The move must be to the FROM clause to join to the driver table (Employees in this example), e.g.

    SELECT
        Emp.EmployeeID,
        xrec.Name AS EmpName
    FROM Employees AS Emp
        LEFT OUTER JOIN
        (SELECT xmlfiles.xmldocID,
            e.value('@ID[1]','int') AS EmployeeID,
            e.value('/Name[1]','varchar(100)') AS Name
        FROM xmlfiles
        	CROSS APPLY fieldXML.nodes('/Employee') x(e)) AS xrec
        	ON Emp.xmldocID = xrec.xmldocID
        	AND Emp.EmployeeID = xrec.EmployeeID
    

    The above example makes use of both a subquery and the APPLY function, by expanding out the nodes of the XML and then joining on matching IDs with the driver table. This ensures that the XML query is not run for each row of the Employees table.

    There are many ways to re-write queries to make use of subqueries, the APPLY function or other methods in order to reduce executions and reads for performance gains. The example above is only one method.

    Replied on Oct 18 2010 11:42AM  . 
    Mike Lewis
    42 · 4% · 1336
  • Score
    9

    What is the data type of the result of a CASE function?

    Quoting Books Online (and practically everyone that has answered this already :) ):

    Returns the highest precedence type from the set of types in result_expressions and the optional else_result_expression.

    An important piece of information that is imperative to appropriately applying this principal to reality is described on the Data Type Precedence information from Books Online (emphasis added):

    When an operator combines two expressions of different data types, the rules for data type precedence specify that the data type with the lower precedence is converted to the data type with the higher precedence. If the conversion is not a supported implicit conversion, an error is returned. When both operand expressions have the same data type, the result of the operation has that data type.

    What does this mean? Basically, if the lower data type will not implicitly convert to the higher, a runtime error will be returned. Consider the following example that will return such error:

    select
        case
            when 1=1 then 'a'
            else 1
        end
    

    Can you use the CASE function to simulate dynamic ORDER BY clause? If yes, how?

    Indeed, the CASE function is quite capable of simulating a dynamic ORDER BY clause. Consider the following (note: this will only work in 2008):

    declare @sort int = 2;
    
    select
        num
        ,chr
    from (values(1,'d'),(2, 'c'),(3, 'b'),(4, 'a')) t(num, chr)
    order by
        case @sort
            when 2 then chr
            else cast(num as char(1))
        end
    

    Again, it's important to note that the resulting data types be able to implicitly convert without error. In this case, I chose to cast the integer typed column as a character as the sorting would still be accurate.

    Demonstrate how you can use the APPLY operator or a subquery to avoid executing same query multiple times when the query (including shredding an xml doc) is part of the CASE function.

    Assuming that I've understood what we're after here, the following should provide an adequate example:

    with T(id, steps) as
    (
        select
            *
        from (values(1, cast('<root>
          <location locationid="10">
             <step>1</step>
             <step>2</step>
          </location>
          <location locationid="20">
             <step>2</step>
             <step>3</step>
          </location>
          <location locationid="30">
             <step>3</step>
             <step>4</step>
          </location>
        </root>' as xml))) tbl(id, steps)
    )
    select
        case f.a
            when 10 then 'Dallas'
            when 20 then 'New York City'
            when 30 then 'Orlando'
            else 'Unknown'
        end
    from T
    cross apply steps.nodes('root/Location') as T2(Loc)
    cross apply (select T2.Loc.value('@LocationID', 'int')) f(a)
    

    You'll notice that we had to use CROSS APPLY to traverse until we got to the value for which we were after (in this case, the LocationID attribute). If we had not, the CASE function causes an execution of the .value method for each option. Below is the query plan:

    Query Plan

    The inefficient alternative would have looked something like this:

    with T(id, steps) as
    (
        select
            *
        from (values(1, cast('<root>
          <location locationid="10">
             <step>1</step>
             <step>2</step>
          </location>
          <location locationid="20">
             <step>2</step>
             <step>3</step>
          </location>
          <location locationid="30">
             <step>3</step>
             <step>4</step>
          </location>
        </root>' as xml))) tbl(id, steps)
    )
    select
        case T2.Loc.value('@LocationID', 'int')
            when 10 then 'Dallas'
            when 20 then 'New York City'
            when 30 then 'Orlando'
            else 'Unknown'
        end
    from T
    cross apply steps.nodes('root/Location') as T2(Loc)
    

    alt text

    Very subtle difference, but the query plan nearly says it all. It should be noted that for every additional option on the CASE funtion, this query plan will grow by another execution of the .value method. However, the former query plan remains exactly the same.

    Replied on Oct 23 2010 10:48PM  . 
    Scott Epperly
    157 · 1% · 301
Previous 1 | 2 Next

Your Answer


Sign Up or Login to post an answer.
Please note that your answer will not be considered as part of the contest because the competition is over. You can still post an answer to share your knowledge with the community.

Copyright © Rivera Informatic Private Ltd.