Okay, so I know from this question why I cannot reference an aliased column from WHERE
, GROUP BY
, or HAVING
statements.
My problem is that I have this query which is being moved from a Teradata database to SQL Server 2012.
In Teradata, referencing an aliased column in the where, group by, having, and even join statements is perfectly valid.
My question is, how can I perform this query, and others like it, in SQL Server, without having to resort to populating a temporary table to select from first. (This example is just a single part of a large tSQL script containing 10 separate transactions, many of which or more complex than the example provided)
SELECT
MAX(CASE WHEN
Field_Name = 'Parent Brand Cd' AND
DATALENGTH(Field_Val)>1
THEN SUBSTRING(Field_Val, 1, DATALENGTH(Field_Val) - 1)
ELSE NULL
END
) AS Parent_Brand_Cd,
MAX(CASE WHEN
Field_Name = 'Brand Id' AND
DATALENGTH(Field_Val)>1
THEN SUBSTRING(Field_Val, 1, DATALENGTH(Field_Val) - 1)
ELSE NULL
END
) AS Hotel_Cd,
@src_sys_id AS Src_Sys_Id,
MAX(CASE WHEN
Field_Name = 'Brand' AND
DATALENGTH(Field_Val)>1
THEN SUBSTRING(Field_Val, 1, DATALENGTH(Field_Val) - 1)
ELSE NULL
END
) AS Temp1,
CASE Temp1
WHEN 'Company1'
THEN 'c1'
WHEN 'Company2'
THEN 'c2'
WHEN 'Company3'
THEN 'c3'
ELSE TEmp1
END AS Brand_Cd,
@process_id AS Insert_Process_Id
FROM dbo.Company -- STAGING
GROUP BY Parent_Brand_Cd
HAVING
Parent_Brand_Cd IS NOT NULL AND
Hotel_Cd IS NOT NULL
The first issue with this query is that it is creating an aliased column Temp1
and then immediately attempting to perform a CASE
statement against it. I can correct this by doing this:
MAX(CASE WHEN
Field_Name = 'Brand' AND
DATALENGTH(Field_Val)>1
THEN SUBSTRING(Field_Val, 1, DATALENGTH(Field_Val) - 1)
ELSE NULL
END
) AS Temp1,
MAX(CASE WHEN
Field_Name = 'Brand' AND
DATALENGTH(Field_Val)>1
THEN
CASE
WHEN SUBSTRING(Field_Val, 1, DATALENGTH(Field_Val) - 1) = 'Company1' THEN 'c1'
WHEN SUBSTRING(Field_Val, 1, DATALENGTH(Field_Val) - 1) = 'Company2' THEN 'c2'
WHEN SUBSTRING(Field_Val, 1, DATALENGTH(Field_Val) - 1) = 'Company' THEN 'c3'
ELSE SUBSTRING(Field_Val, 1, DATALENGTH(Field_Val) - 1)
END
ELSE NULL
END
) AS Brand_Cd,
But this will not help on other parts of the script where the aliased columns are calculation that are then used in other calculations. Also, it does not solve the issue of the aliased columns in the Group By
or Having
statements.
Is there any way around the limitations of Aliased Columns in SQL Server, without having to create and populate temporary tables all over the place?
EDIT: Working Solution as Proposed by GarethD
SELECT
Parent_Brand_Cd,
Hotel_Cd,
@src_sys_id AS Src_Sys_Id,
CASE Temp1
WHEN 'Company1' THEN 'C1'
WHEN 'Company2' THEN 'C2'
WHEN 'Company3' THEN 'C3'
ELSE TEmp1
END AS Brand_Cd,
@process_id AS Insert_Process_Id,
@process_id AS Update_Process_Id
FROM
(
SELECT
MAX(CASE WHEN Field_Name = 'Parent Brand Cd' THEN FieldValue END) AS Parent_Brand_Cd,
MAX(CASE WHEN Field_Name = 'Brand Id' THEN FieldValue END) AS Hotel_Cd,
MAX(CASE WHEN Field_Name = 'Brand' THEN FieldValue END) AS Temp1
FROM
(
SELECT
Field_Name,
FieldValue = CASE WHEN DATALENGTH(Field_Val) > 1 THEN SUBSTRING(Field_Val, 1, DATALENGTH(Field_Val) - 1) END
FROM DEV_STG_TB.dbo.Company_Attributes_3 -- STAGING
) AS c
) AS sub
WHERE
Parent_Brand_Cd IS NOT NULL AND
Hotel_Cd IS NOT NULL
GROUP BY
Parent_Brand_Cd,
Hotel_Cd,
Temp1