Search code examples
sqlt-sqlsubquerywindow-functionsself-join

Convert multiple self JOINs to window function or subqueries (SQL)


I have a query with several self joins:

SELECT t2.Name, t2.Date as date, t2.Value as value1, t3.Value as value2, t4.Value as value3
FROM table_t t1
    RIGHT JOIN #tempPredefinedIndicators t2
        ON t1.Name = t2.Name
    JOIN #tempPredefinedIndicators t3 
        ON t2.Name = t3.Name AND t2.Date = t3.Date
    JOIN #tempPredefinedIndicators t4 
        ON t2.Name = t4.Name AND t2.Date = t4.Date    
WHERE t1.ValueName = 'one' AND DATEDIFF(year, ISDATE(t1.Value), GETDATE()) >=10
AND (t2.ValueName = 'two' AND TRY_CONVERT(FLOAT, t2.Value) > 0.15)
AND (t3.ValueName = 'three' AND TRY_CONVERT(FLOAT, t3.Value) BETWEEN 0 AND 0.5)
AND (t4.ValueName = 'four' AND TRY_CONVERT(FLOAT, t4.Value) > 0.15)

Here is a sample table where in yellow I marked the record that is within the boundaries of the where condition:

enter image description here

Here is the expected result view:

enter image description here

Basically I filter one table with several consecutive conditions and show the result as a table.

Is there a way, using window function or subquery to transform it to be faster?


Solution

  • You could improve performance by removing type conversions, adding indicies to the appropriate columns being queried so often, or by replacing a 4-table join with a PIVOT instead.

    SELECT * FROM (
      SELECT
        [name],
        [valuename],
        [value]
      FROM table_t
      WHERE 
        (valuename = 'one' and datediff(year, isdate(value), getdate()) > 10)
         or 
        (valuename = 'two' and TRY_CONVERT(FLOAT, Value) > 0.15)
         or 
        (ValueName = 'three' AND TRY_CONVERT(FLOAT, Value) BETWEEN 0 AND 0.5)
         or
        (ValueName = 'four' AND TRY_CONVERT(FLOAT, Value) > 0.15)
    ) a
    PIVOT (
      MAX([value])
      FOR [valuename]
      IN (
        [one], [two], [three], [four]
      )
    ) AS PivotTable
    

    Teach yourself through examples here: https://www.sqlshack.com/dynamic-pivot-tables-in-sql-server/

    Your query took 30ms to run in sql-fiddle; it only took 17ms to run the pivot w/o type-conversions in the WHERE clause, and 20-22ms to run with all the WHERE clause conversions.