Search code examples
sqlsql-servergroup-bycursor

How can I add a sub-query to this cursor?


I tried to add a sub query (StoCount) to the following cursor:

        DECLARE trans_cur CURSOR FOR
        SELECT b.TransportNumber, 
            SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed, 
            COUNT(*) AS Total,
            SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
            (SELECT COUNT(*) FROM StorageTransportOrderItem WHERE DeliveryNumber = a.DeliveryNumber AND DeliveryItemNumber = a.DeliveryItemNumber)  As StoCount
           FROM DeliveryItem a
           INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
           INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
           INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
           WHERE a.StorageLocationNumber IS NOT NULL
                AND a.Deleted <> 1
                AND c.CommissioningArea LIKE @commissioningArea 
                AND d.TransportStatus < 70
           GROUP BY b.TransportNumber

but when I always get the error message:

Msg 8120, Level 16, State 1, Procedure sp_CalculateTransportProgress, Line 41 Column 'DeliveryItem.DeliveryNumber' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. Msg 8120, Level 16, State 1, Procedure sp_CalculateTransportProgress, Line 41 Column 'DeliveryItem.DeliveryItemNumber' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

My goal is to add this single column (StoCount) to the cursor without modifying the query too much. Is that possible?


Solution

  • You could move the correlated subquery to a cross apply

    SELECT b.TransportNumber, 
            SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed, 
            COUNT(*) AS Total,
            SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
            MAX(e.Freq) AS StoCount
    FROM DeliveryItem a
    INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
    INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
    INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
    CROSS APPLY (
        SELECT COUNT(*) freq FROM StorageTransportOrderItem  s
        WHERE s.DeliveryNumber = a.DeliveryNumber AND s.DeliveryItemNumber = a.DeliveryItemNumber
    ) e
    WHERE a.StorageLocationNumber IS NOT NULL
      AND a.Deleted <> 1
      AND c.CommissioningArea LIKE @commissioningArea 
      AND d.TransportStatus < 70
    GROUP BY b.TransportNumber
    

    Edit by xsl:

    I had to modify the query a bit, so that it returned the correct results for my database:

            SELECT b.TransportNumber, 
                    SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed, 
                    COUNT(*) AS Total,
                    SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
                    SUM(e.Freq) AS StoCount
            FROM DeliveryItem a
            INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
            INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
            INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
            CROSS APPLY (
                SELECT COUNT(1) freq FROM StorageTransportOrderItem s
                WHERE 
                    s.DeliveryNumber = a.DeliveryNumber
                    AND s.DeliveryItemNumber = a.DeliveryItemNumber
                    AND s.MaterialNumber = a.MaterialNumber
            ) e
            WHERE a.StorageLocationNumber IS NOT NULL
              AND a.Deleted <> 1
              AND c.CommissioningArea LIKE @commissioningArea 
              AND d.TransportStatus < 70
            GROUP BY b.TransportNumber