-1

So I have the SQL statement below and it works:

SELECT T1.*,
       (SELECT COUNT(T3.CTransaction) FROM GBTransaction T3 
        WHERE T3.CSite = 'Store' 
        and   T3.CTransactionType = 'Release' 
        and   T3.CReference = T1.CTransaction) as releasecount 
FROM   GBTransaction T1 
where  T1.CSite = 'Store' 
and    T1.CTransactionType = 'Layaway' 
and    T1.CStatus = 'Active' 
and    T1.CBalance <= 0 
order by T1.CBalance, T1.CDueDate, T1.CTransaction

Basically I'm determining if there is a reference record existing through (SELECT COUNT(T3.CTransaction) FROM GBTransaction T3 WHERE T3.CSite = 'Store' and T3.CTransactionType = 'Release' and T3.CReference = T1.CTransaction) as releasecount

But if I add another WHERE condition which is AND releasecount > 0, SQL Server says

Invalid column name releasecount.

The final statement including the added WHERE condition is the one below:

SELECT  T1.*,
        (SELECT COUNT(T3.CTransaction) FROM GBTransaction T3 
         WHERE  T3.CSite = 'Store' 
         and    T3.CTransactionType = 'Release' 
         and    T3.CReference = T1.CTransaction) as releasecount 
FROM    GBTransaction T1 
where   T1.CSite = 'Store' 
and     T1.CTransactionType = 'Layaway' 
and     T1.CStatus = 'Active' 
and     T1.CBalance <= 0 
and     releasecount > 0 
order by T1.CBalance, T1.CDueDate, T1.CTransaction

I'm confused and have no idea why it doesn't work? Thank you so much.

Dale K
  • 25,246
  • 15
  • 42
  • 71
chris_techno25
  • 2,401
  • 5
  • 20
  • 32

1 Answers1

2

You are attempting to use a "column alias" in the where clause of the same query. This isn't possible in SQL Server (and in many other databases). Without going into enormous detail, the clause order of select to order by is NOT the way the query is executed - which starts with the from & where clauses. So in the where clause (executed before the select clause) the column alias can't be referenced.

There is another way to execute that "correlated sub-query" using an "apply operator". Here we can use a cross apply. Two advantages of this approach are:

  • it is generally faster than the approach in your original query, and
  • because apply operators are part of the from clause you can include the column alias in the subsequent where clause.
    SELECT T1.*
        , oa.releasecount
    FROM GBTransaction T1
    CROSS APPLY (
        SELECT COUNT(T3.CTransaction) AS releasecount
        FROM GBTransaction T3
        WHERE T3.CSite = 'Store'
            AND T3.CTransactionType = 'Release'
            AND T3.CReference = T1.CTransaction
        ) oa
    WHERE T1.CSite = 'Store'
        AND T1.CTransactionType = 'Layaway'
        AND T1.CStatus = 'Active'
        AND T1.CBalance <= 0
        AND oa.releasecount > 0
    ORDER BY T1.CBalance
        , T1.CDueDate
        , T1.CTransaction1
Paul Maxwell
  • 33,002
  • 3
  • 32
  • 51
  • Thank you so much. Your solution works! This is the first time I've heard about Cross Apply. I still don't know how to use it but I'm reading about it now. Thank you again. – chris_techno25 Aug 20 '23 at 05:42
  • 1
    There is also `outer apply` which is similar to a `left join` (`cross apply` is similar to `inner join`). Now you know about apply operators you may never have to use a "correlated subquery" in the select clause ever again. https://learn.microsoft.com/en-us/sql/t-sql/queries/from-transact-sql?view=sql-server-ver16#using-apply – Paul Maxwell Aug 20 '23 at 05:51