参考粗体部分,基本上有产品代码,并在案例说明中添加产品的合格年龄。所以下面我们有年龄为 18 岁或 14 岁的产品来使用产品。创建了一个新列作为“资格”
现在提到第二个粗体部分,我只想要“资格”>“AgeAtOpenDate”的账户,即账户持有人对于账户来说太年轻了。
SELECT
CASE
WHEN EOMONTH(OpenDate,0) = a.[EtlFileDate] THEN 'New Account'
ELSE 'Existing Account'
END AS 'NewAccountsInMonth'
,CASE
**WHEN a.[ProductCode] in (801,802) THEN '18'
WHEN a.[ProductCode] in (480,481,489,490) THEN '14'
END as 'Eligibility'**
,a.[EtlFileDate]
,a.[AccountNumber]
,a.[OpenDate]
,a.[ProductCode]
,a.[ProductName]
,a.[PrimaryCAN]
,b.[Cust_Age]
,b.[Cust_BirthDate]
,**(DATEDIFF(year,b.[Cust_BirthDate],a.[OpenDate] ) as 'AgeAtOpenDate'**
FROM Histaccounts a
join Marketable b
on a.[PrimaryCAN]=b.[CAN]
**where 'Eligibility'>'AgeAtOpenDate'**
and a.[EtlFileDate] between '2021-10-31' and '2023-03-23'
and a.[ProductCode] in (480,481,489,490,802,801)
当我运行上面的脚本时,我仍然得到所有结果,而不是未满年龄的结果。
我做错了什么?这是否与您不能在 SELECT 区域中使用基于 CASE 的 WHERE 条件有关?
问题是您不能在 SELECT 语句中定义的 WHERE 子句中使用别名。 WHERE 子句在 SELECT 语句之前求值,因此别名
Eligibility
和 AgeAtOpenDate
在 WHERE 子句中不被识别。
您可以这样重写您的查询:
SELECT *
FROM (
SELECT
CASE
WHEN EOMONTH(OpenDate,0) = a.[EtlFileDate] THEN 'New Account'
ELSE 'Existing Account'
END AS 'NewAccountsInMonth',
CASE
WHEN a.[ProductCode] in (801,802) THEN '18'
WHEN a.[ProductCode] in (480,481,489,490) THEN '14'
END as 'Eligibility',
a.[EtlFileDate],
a.[AccountNumber],
a.[OpenDate],
a.[ProductCode],
a.[ProductName],
a.[PrimaryCAN],
b.[Cust_Age],
b.[Cust_BirthDate],
DATEDIFF(year,b.[Cust_BirthDate],a.[OpenDate] ) as 'AgeAtOpenDate'
FROM Histaccounts a
JOIN Marketable b
ON a.[PrimaryCAN]=b.[CAN]
WHERE a.[EtlFileDate] BETWEEN '2021-10-31' AND '2023-03-23'
AND a.[ProductCode] IN (480,481,489,490,802,801)
) subquery
WHERE subquery.Eligibility > subquery.AgeAtOpenDate
这里有几个问题,但最大的是
'Eligibility'
子句中的值 'AgeAtOpenDate'
和 WHERE
被解释为字符串文字,而不是对列别名的引用,并且由于 E
大于 A
条件总是成功。
您可以通过多种方式解决此问题,但在这种情况下,您最好不要重复
CASE
表达式。做exactly,SQL Server足够聪明,知道SELECT
和WHERE
子句中的表达式是相同的,只会计算一次。任何类型的嵌套或分层,您都有可能失去对可能有助于查询的索引的使用。
你能尝试用整个逻辑替换 in where 子句吗
where (CASE WHEN a.[ProductCode] in (801,802) THEN '18'
WHEN a.[ProductCode] in (480,481,489,490) THEN '14'
END > (DATEDIFF(year,b.[Cust_BirthDate],a.[OpenDate] > (DATEDIFF(year,b.[Cust_BirthDate],a.[OpenDate] )) > (DATEDIFF(year,b.[Cust_BirthDate],a.[OpenDate] )) and a.[EtlFileDate] between '2021-10-31' and '2023-03-23' and a.[ProductCode] in (480,481,489,490,802,801)
您可以在临时表中插入记录,然后应用过滤器
SELECT
CASE
WHEN EOMONTH(OpenDate,0) = a.[EtlFileDate] THEN 'New Account'
ELSE 'Existing Account'
END AS 'NewAccountsInMonth'
,CASE WHEN a.[ProductCode] in (801,802) THEN '18'
WHEN a.[ProductCode] in (480,481,489,490) THEN '14'
END as 'Eligibility'
,a.[EtlFileDate]
,a.[AccountNumber]
,a.[OpenDate]
,a.[ProductCode]
,a.[ProductName]
,a.[PrimaryCAN]
,b.[Cust_Age]
,b.[Cust_BirthDate]
,(DATEDIFF(year,b.[Cust_BirthDate],a.[OpenDate] ) as [AgeAtOpenDate]
into #Test
FROM Histaccounts a
join Marketable b
on a.[PrimaryCAN]=b.[CAN]
WHERE a.[EtlFileDate] between '2021-10-31' and '2023-03-23' and a.[ProductCode] in (480,481,489,490,802,801)
SELECT * from #Test
WHERE Eligibility>AgeAtOpenDate
CTE
WITH CTE AS
(
SELECT
CASE
WHEN EOMONTH(OpenDate,0) = a.[EtlFileDate] THEN 'New Account'
ELSE 'Existing Account'
END AS 'NewAccountsInMonth'
,CASE WHEN a.[ProductCode] in (801,802) THEN '18'
WHEN a.[ProductCode] in (480,481,489,490) THEN '14'
END as 'Eligibility'
,a.[EtlFileDate]
,a.[AccountNumber]
,a.[OpenDate]
,a.[ProductCode]
,a.[ProductName]
,a.[PrimaryCAN]
,b.[Cust_Age]
,b.[Cust_BirthDate]
,(DATEDIFF(year,b.[Cust_BirthDate],a.[OpenDate] ) as [AgeAtOpenDate]
into #Test
FROM Histaccounts a
join Marketable b
on a.[PrimaryCAN]=b.[CAN]
WHERE a.[EtlFileDate] between '2021-10-31' and '2023-03-23' and a.[ProductCode] in (480,481,489,490,802,801)
)
SELECT * from CTE
WHERE Eligibility>AgeAtOpenDate