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:
Here is the expected result view:
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?
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.