How to Use Joins Instead of Subquery in SQL Server

greatest-n-per-groupmaterialized-viewsql serversql server 2014subquery

I am using SQL Server 2014 and I want to eliminate having to use the following sub query so I can create an indexed view.

The only thing similar to my problem is the greatest-n-per-group queries but I want all the values, instead of only the last measured factor ones.

This is my query:

SELECT
      eu.[Name],
      pp.[MonthDay] --date type,
      pp.[Value] * 
            (SELECT TOP 1 [Factor] FROM [em].[CO] co 
            WHERE co.[EUID] = eu.[Name] 
            AND co.[MonthDay] <= pp.MonthDay 
            ORDER BY [MonthDay] DESC) AS [CO]
            --multiply by the last measured factor
            --I also want to remove the sub query
FROM em.[PPGenData] pp
JOIN em.[PPEUID] eu
ON eu.ID = pp.ID

Best Answer

I think this will do it, but like Aaron said it would be more useful to have the context around the rewrite. You can probably write this more simply using WHERE EXISTS() rather than TOP 1 or ROW_NUMBER(), but without knowing your schema I'd rather not speculate.

SELECT
    EU.Name,
    PP.MonthDay,
    PP.Value * Y.Factor AS CO
FROM
    em.PPGenData AS PP
    INNER JOIN em.PPEUID AS EU ON PP.ID = EU.ID
    LEFT JOIN
        (
        SELECT
            ID, Factor
        FROM
            (
            SELECT
                PP2.ID, CO.Factor, ROW_NUMBER() OVER (PARTITION BY PP2.ID ORDER BY CO.MonthDay DESC) AS Seq
            FROM
                em.PPGenData AS PP2
                INNER JOIN em.PPEUID AS EU2 ON PP2.ID = EU2.ID
                INNER JOIN em.CO AS CO ON EU2.Name = CO.EUID
            WHERE
                CO.MonthDay < PP.MonthDay
            ) AS X
        WHERE
            Seq = 1
        ) AS Y ON PP.ID = Y.ID

Note that subquery X needs to be wrapped in another subquery since a windowed function cannot be used in a WHERE clause.