Reference an alias for an expression in a SELECT statement - sql

I have the following select statement that creates the expression "newdate" and then references in a different expression called "newname":
SELECT
Iif([DateColumn1]='',Format(CONVERT(DATE,Dateadd(day,RIGHT([DateColumn2],3)-1,CONVERT(DATETIME,LEFT([DateColumn2],4)))),'MMddyy'),Format(CONVERT(DATE,Dateadd(day,RIGHT(datecolumn3],3)-1,CONVERT(DATETIME,LEFT([DateColumn3],4)))),'MMddyy')) AS **newdate**,
Upper(LEFT(Rtrim([NameColumn4]),19)+''+[newdate]+''+RIGHT([NameColumn5],3)) AS newname
FROM table1
For some reason when running this I get an error of invalid column and it refers to the "newdate" expression I created. The "newdate" expression works fine but it's when I add the second expression for "newname" that it stops working.
Is there a way to refer to an expression as an alias within another expression that also has an alias?

You can't. But SQL Server has a very nifty feature where you can define the column in the from clause using apply:
SELECT v.newdate,
Upper(LEFT(Rtrim(t1.[NameColumn4]),19) + v.newdate + RIGHT(t1.[NameColumn5], 3)) AS newname
FROM table1 t1 CROSS APPLY
(VALUES ( <complicated expression here)
) v(newdate)

You can't reference an alias within the same scope as its created - you can create it in a sub-query if you wish to avoid repeating the logic.
SELECT
UPPER(LEFT(RTRIM([NameColumn4]),19)+''+[newdate]+''+RIGHT([NameColumn5],3)) AS [NewName]
FROM (
SELECT NameColumn4, NameColumn5
, IIF([DateColumn1]='',FORMAT(CONVERT(DATE,DATEADD(DAY,RIGHT([DateColumn2],3)-1,CONVERT(DATETIME,LEFT([DateColumn2],4)))),'MMddyy'),FORMAT(CONVERT(DATE,DATEADD(DAY,RIGHT(datecolumn3],3)-1,CONVERT(DATETIME,LEFT([DateColumn3],4)))),'MMddyy')) AS NewDate
FROM table1
) X

In SQL Server, there is a concept called ALL AT ONCE, where all operations on a logical query execution phase (SELECT here).So, you are facing issue here.
Detailed Information on All at Once
SELECT FirstName + LastName AS FullName,
Salutation + FullName -- Will throw error here
FROM TableName
You can handle that through multiple ways:
Sub queries Dale K has suggested in another answer
Common Table Expression Given below
;WITH CTE_NewDate AS
(
SELECT
Iif([DateColumn1]='',Format(CONVERT(DATE,Dateadd(day,RIGHT([DateColumn2],3)-1,CONVERT(DATETIME,LEFT([DateColumn2],4)))),'MMddyy'),Format(CONVERT(DATE,Dateadd(day,RIGHT(datecolumn3],3)-1,CONVERT(DATETIME,LEFT([DateColumn3],4)))),'MMddyy')) AS newdate,
NameColumn4, NameColumn5
FROM table1
)
SELECT newDate, Upper(LEFT(Rtrim([NameColumn4]),19)+''+[newdate]+''+RIGHT([NameColumn5],3)) AS newname
FROM CTE_NewDate

Related

I'm trying to create a query using the SQL SELECT statement

I'm trying to create a query using the SQL SELECT statement but I keep getting a error with my code
This is my code:
SELECT *
FROM tblRegistration
WHERE (tblRegistration.InstanceID IN (
SELECT InstanceID FROM tblRegistration
SELECT tblCourse.InstanceID, tblCourse.HoursPerWeek
FROM tblCourse
WHERE (((tblCourse.HoursPerWeek)=40));
Access throws in far more parentheses in WHERE clause than are needed. Simplify by removing most of them then test. Access will eventually throw them back in if you switch builder between datasheet and design view and save the object. Always make sure brackets, parens, quote marks, and apostrophes are evenly paired.
Also have too many SELECT clauses.
Subquery for IN() must return only one field.
Consider:
SELECT *
FROM tblRegistration
WHERE tblRegistration.InstanceID IN (
SELECT tblCourse.InstanceID
FROM tblCourse
WHERE tblCourse.HoursPerWeek=40);
If you don't want to remove field from subquery, try:
SELECT *
FROM tblRegistration
WHERE EXISTS (
SELECT tblCourse.InstanceID, tblCourse.HoursPerWeek
FROM tblCourse
WHERE tblCourse.HoursPerWeek=40);

How do I add where condition?

I want to add a condition according to the returned result
You can't reuse an alias defined in the SELECT clause in the FROM clause of the scope. You need to either repeat the expression, or use a subquery or CTE.
select dayofweek_iso(timestamp(mycol)) as mynewcol
from mytable
where dayofweek_iso(timestamp(mycol)) = 1
Or:
select *
from (
select dayofweek_iso(timestamp(mycol)) as mynewcol
from mytable
) t
where mynewcol = 1
Use your existing query as a subquery:
select * from (
<add your existing query in the screenshot here>
) t
where <add your conditions here>
i think you should include your code in the post itself. A picture like this is quite unhandy.
W3: SQL WHERE
as you can see here, just add your WHERE statement at the end:
SELECT * FROM XXX WHERE CONDITION
Out of interest, since Db2 11.5, you can reference a column alias in a WHERE clause if using NPS (i.e. Netezza compatibility) mode.
CREATE TABLE MYTABLE(MYCOL DATE)
SET SQL_COMPAT='NPS'
SELECT DAYOFWEEK_ISO(TIMESTAMP(MYCOL)) AS MYNEWCOL
FROM MYTABLE
WHERE MYNEWCOL = 1
Still, this is best reserved for users migrating from Netezza as NPS mode changes some other things too.

Redshift - CASE statement checking column EXISTS or no

I am querying dynamically tables where some of the tables might not have specific column. My intention is check the existence of the column and dynamically assign a value. Basically if all the tables would contain the field I would just write simply :
select name, count(k_val) from tbl GROUP by 1
But in my case I need to do something like this:
select name,
SUM( (CASE when (select EXISTS( SELECT * FROM pg_table_def WHERE tablename = 'tbl'
and "column" = 'k_val'))
then 1 else 0 end) ) as val
from tbl GROUP by 1
I am getting the error:
SQL Error [500310] [0A000]: Amazon Invalid operation:
Specified types or functions (one per INFO message) not supported on
Redshift tables.;
The following is a trick that works on most databases to handle missing columns.
select t.*,
(select k_val -- intentionally not qualified
from tbl t2
where t2.pk = t.pk
) new_k_val
from tbl t cross join
(select NULL as k_val) k;
pk is the primary key column for the table. This uses scoping rules to find a value for k_val. If k_val is in the table, then the subquery will use the value from that row. If not, then the scope will "reach out" and take the value from k. There is no confusion in this case, because k_val is not in tbl.
If you don't want a constant subquery for some reason, you can always use:
(select NULL as k_val from t limit 1) k
You can then use this as a subquery or CTE for your aggregation purposes.
Having said all that, I am wary of handling missing columns this way.

What is the "DATA" keyword in T-SQL for?

I'm working with a database in T-SQL/SQL Server 2016 at the moment which has some stored procedures containing a keyword I'm not familiar with, namely the "DATA" suffix after a query:
SELECT * FROM dbo.TableName DATA
I'm struggling to find any documentation on what the purpose of this "DATA" keyword is. Could someone shed some light please?
It is not some specific keyword. It is just a table alias. Note that if you changed your select to
SELECT DATA.* FROM dbo.TableName DATA
it will work, as the table now has the "DATA" alias. For the same reason, this:
SELECT dbo.TableName.* FROM dbo.TableName DATA
will throw an error.
This is an alias for the table name, usually it is used if we are inner joining the same table more than one time, or when we need to call the table with a shortcut name.
For example if the table has a key named ID, then:
SELECT DATA.* FROM dbo.TableName DATA
where DATA.ID = "1"
is like
SELECT dbo.TableName.* FROM dbo.TableName
where TableName .ID = "1"

Table name after parenthesis notation

I was going through some old-ish SQL code someone else had written that I couldn't quite understand. I have simplified its structure here, but if anyone can walk me through what exactly is going on, that would be appreciated! You may ignore the specific column operations as they were just examples.
SELECT table.*,
column1 - column2
AS 'col1 - col2',
...
columnn
AS 'coln'
FROM
(SELECT
...
) table
What I don't understand is the final line. I am assuming it is the definition of "table" in the FROM (SELECT ...) part, and the ) table part indicates the name of the defined table.
Thanks in advance!
An inner select needs an alias name
select alias_name.* from
(
select * from some_table ...
) alias_name
The 'table' in that final line is an alias for the subquery.
In T-SQL it is AFAIK mandatory to specify an alias for a subquery if you're selecting from a subquery.
You can name the alias whathever you want. It is perfectly ok to use it like this
select * from
( select * from ... ) as X
(The as keyword is not mandatory, but I always specify the alias-name using 'as').