Can a column name used as part of a CTE be used in the SELECT query that creates the CTE?

Gil Robinson 0 Reputation points
2025-05-09T13:15:11.4133333+00:00

When converting a SQL script from SQL Anywhere to SQL Server, my code generated an error for the following CTE code sample; the error says that the column name used in the ROW_NUMBER function is invalid. Any suggestions on how to fix this would be appreciated:

With TestCTE(CUST_NUM, FIRST_NAME, LAST_NAME, ADDRESS, ROWNUM) as(

SELECT

 testDB.FIELD_1 as CUST_NUM

 testDB.FIELD_2 as FIRST_NAME,

 testDB.FIELD_3 as LAST_NAME,

 testDB.FIELD_4 as TRANACTION_NUMBER,

 CASE
	WHEN TRANSACTION_TYPE = 'D' THEN 'DEPOSIT'
	WHEN TRANSACTION_TYPE = 'W' TEN 'WITHDRAWAL'
	WHEN TRANSACTION_TYPE = 'L' THEN 'LOAN'
	ELSE 'PAYMENT'
 END TRANS_TYPE,

 ROW_NUMBER() OVER(PARTITION by testDB.FIELD_1 ***order by TRANS_TYPE*****)** as ROWNUM
FROM

testDB

SQL Server Transact-SQL
SQL Server Transact-SQL
SQL Server: A family of Microsoft relational database management and analysis systems for e-commerce, line-of-business, and data warehousing solutions.Transact-SQL: A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.
181 questions
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Naomi Nosonovsky 8,351 Reputation points
    2025-05-09T20:05:01.6666667+00:00

    Try

    TestCTE(CUST_NUM, FIRST_NAME, LAST_NAME, ADDRESS, ROWNUM) as(
    
    SELECT
    
    SQL
    
    Copy
     testDB.FIELD_1 as CUST_NUM
    
     testDB.FIELD_2 as FIRST_NAME,
    
     testDB.FIELD_3 as LAST_NAME,
    
     testDB.FIELD_4 as TRANACTION_NUMBER,
    
     
     ROW_NUMBER() OVER(PARTITION by testDB.FIELD_1 order by T.TRANS_TYPE) as ROWNUM
    FROM
    testDB CROSS APPLY (select 
    CASE 	WHEN TRANSACTION_TYPE = 'D' THEN 'DEPOSIT' 	WHEN TRANSACTION_TYPE = 'W' TEN 'WITHDRAWAL' 	WHEN TRANSACTION_TYPE = 'L' THEN 'LOAN' 	ELSE 'PAYMENT'  END TRANS_TYPE) T 
    
    0 comments No comments

  2. Erland Sommarskog 120.4K Reputation points MVP Moderator
    2025-05-09T20:39:36.6966667+00:00

    The idea in SQL is "all at once". This means that the SELECT list is defined all at once. Therefore, you cannot refer to a column alias defined earlier in the SELECT list in a later column in the SELECT list.

    That is the ANSI standard, but there are more than one product that violates this rule and permits you do this exactly the above. SQL Anywhere is by no means the only sinner. However, SQL Server plays by the book.

    So you need something like:

    With TestCTE(CUST_NUM, FIRST_NAME, LAST_NAME, ADDRESS, ROWNUM) as(
      SELECT  testDB.FIELD_1 as CUST_NUM
              testDB.FIELD_2 as FIRST_NAME,
              testDB.FIELD_3 as LAST_NAME,
              testDB.FIELD_4 as TRANACTION_NUMBER,
              CASE
    	          WHEN TRANSACTION_TYPE = 'D' THEN 'DEPOSIT'
    	          WHEN TRANSACTION_TYPE = 'W' TEN 'WITHDRAWAL'
    	          WHEN TRANSACTION_TYPE = 'L' THEN 'LOAN'
    	          ELSE 'PAYMENT'
             END TRANS_TYPE,
       FROM  tbl
    ), nextCTE AS (
      SELECT CUST_NUM, FIRST_NAME, LAST_NAME, TRANSACTION_NUMBER, 
             ROW_NUMBER() OVER(PARTITION by CUST_NUM TRANS_TYPE) as ROWNUM
       FROM  TestCTE
    )
    
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.