How to reuse column alias in another column within same select statement?
In SQL Server, you can use APPLY
to define column aliases in the FROM
clause -- a good place, in my opinion:
select pd.id v.value_1,
(Case when value_1 in ('test1', 'test2') Then '0'
else value_1
End) as value_2
from pd cross apply
(values ( case . . . )
) v(value_1);
Notes:
- Don't use identifier names that need to be escaped, hence
value_1
instead ofvalue 1
. value_1
appears to be string. Thecase
expression forvalue_2
should return a string, so'0'
instead of0
.- I define table aliases using
as
after the expression. This is the SQL standard, but there is nothing per se wrong with using=
, which is SQL Server specific syntax.
Re-use aliased field in SQL SELECT statement
A workaroud would be to use a sub-query:
SELECT
FieldA,
FieldA + 20 AS FieldB
FROM (
SELECT
(CASE WHEN ...) AS FieldA
FROM Tbl
) t
To improve readability you could also use a CTE
:
WITH t AS (
SELECT
(CASE WHEN ...) AS FieldA
FROM Tbl
)
SELECT
FieldA,
FieldA + 20 AS FieldB
FROM
t
Reuse of alias in a query
In order to access to fname
, you need to put your query inside a sub-query as below:
SELECT K.fname, K.lname, K.fname as NewFname
FROM(
SELECT 'Santosh' as fname, 'Jadi' as lname
) as K
Why is mySQL able to resolve these column aliases when normally one can't reuse an alias?
This looks like a parsing bug to me (in other databases, you would get an error on the first two queries).
I can guess at what is happening. MySQL is parsing the subquery (select c1)
. It doesn't find c1
in the subquery, so it starts looking for references in outer queries.
According to the rules of SQL, it should only be looking at columns in the from
clause. However, MySQL also seems to be looking at column aliases.
Although I would call this a bug, MySQL seems to consider it a feature. (Yet another example of MySQL considering a "bug" a "feature".) Consider this query:
SELECT CONCAT((SELECT c1), 2), CONCAT(a, b) AS c1
FROM (SELECT 'a' a, 'b' b, 'c' c UNION ALL
SELECT '1', '2', '3') t1;
And the error it generates:
Reference 'c1' not supported (forward reference in item list)
The error suggests that MySQL is intentionally parsing "backwards" references.
For the record, I would never depend on this functionality. It is not only a violation of the ANSI standard and unique behavior among databases. It is confusing. Consider this little modification:
SELECT CONCAT(a, b) AS c1, CONCAT((SELECT c1), 2)
FROM (SELECT 'a' a, 'b' b, 'c' c UNION ALL
SELECT '1', '2', '3') t1 CROSS JOIN
(SELECT 'abcdef' as c1) x;
Which c1
does the query resolve to? I'll let you figure that out. And this doesn't even take into account that c1
could be a variable.
SQL Server reuse aliases in subqueries
I think that following script can explain you everything.
SELECT 1,1,GETDATE()
INSERT INTO @t ( Id, UserId, TranDate )
SELECT 2,1,GETDATE()
INSERT INTO @t ( Id, UserId, TranDate )
SELECT 3,1,GETDATE()
SELECT tx.Id/*main alias*/,
tx1.Id /*First subquery alias*/,
tx2.Id /*Second subquery alias*/,
(SELECT Id FROM @t txs /*alias only in this one subquery/must be different from main if you want use main alias in it...*/
WHERE txs.Id = tx.Id+2 /*here is used main value = subquery value+2*/) AS Id
FROM @t tx /*main*/
JOIN (SELECT *
FROM @t tx
WHERE tx.Id = 1 /*this one using subquery values + you are not able to use here main value*/
) tx1 --alias of subquery
ON tx.Id = tx1.Id /*here is used main value = subquery value*/
CROSS APPLY (SELECT TOP 1 *
FROM @t txc /*This one must be different from main if you want use it to comparison with main*/
WHERE txc.Id > tx.Id /*this one using subquery value > main value*/
) tx2 --alias of subquery
WHERE tx.Id = 1 AND /*Subquery alias canot reference on First subquery value*/
tx1.Id = 1 AND/*Subquery alias*/
tx2.Id = 2 /*Subquery alias*/
It means that yea, it could be reused, but only if you dont want compare main / sub, because if you reuse it and for example you try to do folowing statement in subquery tx.Id > tx.Id
It causes that only values in subquery will be compared. In our example it causes that you dont get anything because you comaring values in same row...
Reusing alias for an expression in postgresql
As you observe, what you want to do is not possible. Instead, you can use a lateral join to calculate values in the FROM
clause:
select v.full_name, Length(v.full_name) as len
from customer c cross join lateral
(values (first_name || ' ' || last_name)
) v(full_name)
order by len;
Related Topics
Creating a Trigger to Only Run When a New Table Is Being Created
SQL Server Convert Datetime into Another Timezone
What's the Asymptotic Complexity of Groupby Operation
Maximum and Minimum Number of Tuples in Natural Join
SQL Server: How to Group Multiple Row Values into Separate Columns
How to Return Last Inserted (Auto Incremented) Row Id in Hsql
Ordered Count of Consecutive Repeats/Duplicates
How to Get the Date and Time from Timestamp in Postgresql Select Query
What Is the Resource Impact from Normalizing a Database
SQL Server Query Xml Attribute for an Element Value
How to Use SQL Server Compact Edition Ce on Mono
#1452 - Cannot Add or Update a Child Row: a Foreign Key Constraint Fails
Getting an Error When Executing a Dynamic SQL Within a Function (SQL Server)