是的,我现在已经和它斗争了一段时间,虽然我有一个有效的查询但它让我觉得它不合逻辑。如果我表明我的意思,这会更容易:
我有一张工作表i.d,电子邮件地址,以及应该使用的布尔值'列。
CREATE TABLE LWEmail
(ID int, Email varchar(64), MustUse int)
INSERT INTO LWEmail VALUES(1,'adfgae@asfdvaerg.com',1)
INSERT INTO LWEmail VALUES(1,'sdfghsth@asfdvaerg.com',1)
INSERT INTO LWEmail VALUES(1,'admjury@asfdvaerg.com',0)
INSERT INTO LWEmail VALUES(2,'dyj@asfdvaerg.com',0)
INSERT INTO LWEmail VALUES(2,'adynee@asfdvaerg.com',0)
INSERT INTO LWEmail VALUES(3,'kitu@asfdvaerg.com',1)
INSERT INTO LWEmail VALUES(3,'aswtrhe@asfdvaerg.com',1)
INSERT INTO LWEmail VALUES(3,'abetr@asfdvaerg.com',1)
INSERT INTO LWEmail VALUES(3,'aeryje@asfdvaerg.com',0)
INSERT INTO LWEmail VALUES(3,'eyj@asfdvaerg.com',0)
INSERT INTO LWEmail VALUES(4,'dej@asfdvaerg.com',1)
INSERT INTO LWEmail VALUES(4,'aetyj@asfdvaerg.com',1)
INSERT INTO LWEmail VALUES(4,'ey@asfdvaerg.com',0)
INSERT INTO LWEmail VALUES(5,'egn@asfdvaerg.com',0)
INSERT INTO LWEmail VALUES(5,'egrn@asfdvaerg.com',0)
INSERT INTO LWEmail VALUES(6,'bneyh@asfdvaerg.com',1)
INSERT INTO LWEmail VALUES(6,'eryh@asfdvaerg.com',1)
INSERT INTO LWEmail VALUES(6,'adfeyj@asfdvaerg.com',0)
根据' MustUse'以及将这些电子邮件地址连接到每个ID一行的查询。标准:
SELECT DISTINCT
CONVERT (varchar(24), [LWEmail].[ID]) AS LogBatch,
STUFF((SELECT CAST(', ' + LWEmail2.Email AS VARCHAR(MAX))
FROM [LWEmail] AS LWEmail2
WHERE LWEmail2.[ID] = [LWEmail].[ID] and [MustUse] = 1
FOR XML PATH('')), 1,2,'') AS Emails
FROM [LWEmail]
这会产生:
LOGBATCH EMAILS
1 adfgae@asfdvaerg.com, sdfghsth@asfdvaerg.com
2 (null)
3 kitu@asfdvaerg.com, aswtrhe@asfdvaerg.com, abetr@asfdvaerg.com
4 dej@asfdvaerg.com, aetyj@asfdvaerg.com
5 (null)
6 bneyh@asfdvaerg.com, eryh@asfdvaerg.com
我还希望它忽略该行,如果电子邮件'返回null(第2行和第5行) 所以逻辑上我试图添加:
WHERE Emails IS NOT NULL
最后。这不起作用:'无效的列名称"电子邮件"'。但这确实有效:
SELECT DISTINCT
CONVERT (varchar(24), [LWEmail].[ID]) AS LogBatch,
STUFF((SELECT CAST(', ' + LWEmail2.Email AS VARCHAR(MAX))
FROM [LWEmail] AS LWEmail2
WHERE LWEmail2.[ID] = [LWEmail].[ID] and [MustUse] = 1
FOR XML PATH('')), 1,2,'') AS Email
FROM [LWEmail]
WHERE
STUFF((SELECT CAST(', ' + LWEmail2.Email AS VARCHAR(MAX))
FROM [LWEmail] AS LWEmail2
WHERE LWEmail2.[ID] = [LWEmail].[ID] and [MustUse] = 1
FOR XML PATH('')), 1,2,'') IS NOT NULL
为什么我不能参考电子邮件'作为一个条件,当我想到,由于括号和逻辑顺序,执行路径将使它成为首先执行的事情之一,使其可用于评估?您可以使用转换日期或数学运算来执行此操作。任何见解?为了提高效率,我宁愿参考和评估已经计算过的东西,而不是两次进行计算。只是想学习并且更有效率。
答案 0 :(得分:2)
您说“逻辑顺序”,但从逻辑上讲,SELECT
在 WHERE
之后执行。你可以把它放在子查询中:
SELECT * FROM (
SELECT DISTINCT
CONVERT (varchar(24), [LWEmail].[ID]) AS LogBatch,
STUFF((SELECT CAST(', ' + LWEmail2.Email AS VARCHAR(MAX))
FROM [LWEmail] AS LWEmail2
WHERE LWEmail2.[ID] = [LWEmail].[ID] and [MustUse] = 1
FOR XML PATH('')), 1,2,'') AS Emails
FROM [LWEmail]
) t
where Emails is not null
有关处理订单,请参阅例如维基百科上的Select (SQL):
FROM
ON
WHERE
GROUP BY
HAVING
SELECT
DISTINCT
ORDER BY
此外:
为了提高效率,我宁愿参考和评估已经计算过的东西,而不是两次进行计算。
SQL Server已经有了很多技巧,它可以观察到相同的计算被要求两次,并且将避免实际多次执行计算。另一方面,仅仅因为计算仅在您的语句中出现一次并不保证系统实际上不会多次评估它。
在这种情况下,我同意减少它只是因为它看起来很乱。但是你应该知道,在SQL语言中,你通常会试图告诉系统你想要什么,而不是如何做到。这是优化工作。
答案 1 :(得分:1)
您显然无法调用在同一级别创建的ALIAS
子句上的WHERE
。 SQL Order of Operation
如下:
在ALIAS
子句上创建SELECT
,首先执行WHERE
子句。要从别名调用的唯一解决方案是将整个查询包装在子查询中。例如,
SELECT *
FROM
(
SELECT DISTINCT CONVERT (varchar(24), [LWEmail].[ID]) AS LogBatch,
STUFF(( SELECT CAST(', ' + LWEmail2.Email AS VARCHAR(MAX))
FROM [LWEmail] AS LWEmail2
WHERE LWEmail2.[ID] = [LWEmail].[ID] and
[MustUse] = 1
FOR XML PATH('')), 1,2,'') AS Emails
FROM [LWEmail]
) subQuery
WHERE Emails IS NOT NULL
答案 2 :(得分:1)
尝试:
SELECT *
FROM
(SELECT DISTINCT
CONVERT (varchar(24), [LWEmail].[ID]) AS LogBatch,
STUFF((SELECT CAST(', ' + LWEmail2.Email AS VARCHAR(MAX))
FROM [LWEmail] AS LWEmail2
WHERE LWEmail2.[ID] = [LWEmail].[ID] and [MustUse] = 1
FOR XML PATH('')), 1,2,'') AS Email
FROM [LWEmail] ) Sub
WHERE Email IS NOT NULL