1

そうです、私はしばらくの間これと戦ってきました。私は機能するクエリを持っていますが、それが非論理的であると私を悩ませています。私が何を意味するかを示すと簡単です:

ジョブID、電子メールアドレス、およびブール値の「使用する必要がある」列を含むテーブルがあります。

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 ごとに 1 行に連結するクエリ:

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

また、「Emails」がnullを返した場合(行2と5)に行を無視したかったので、論理的に追加しようとしました:

  WHERE Emails IS NOT NULL

最後に。これは機能しません:「無効な列名 "Emails"」。しかし、これはうまくいきます:

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

括弧と論理的な順序のために、実行パスによって最初に実行されるものの 1 つになり、評価できるようになると思っていたのに、「メール」を条件として参照できないのはなぜですか? これは、たとえば、変換された日付または数学演算で行うことができます。洞察はありますか?計算を 2 回行うよりも、効率のために、既に計算されているものを参照して評価することをお勧めします。本当に学び、より効率的になることを目指しています。

4

3 に答える 3

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

処理順序については、Wikipedia のSelect (SQL)などを参照してください。

  • FROM
  • ON
  • WHERE
  • GROUP BY
  • HAVING
  • SELECT
  • DISTINCT
  • ORDER BY

また:

計算を 2 回行うよりも、効率のために、既に計算されているものを参照して評価することをお勧めします。

SQL Server には、同じ計算が 2 回要求されていることを確認し、実際に計算を複数回実行することを回避する、かなりの数のトリックが用意されています。一方、計算がステートメントに 1 回しか表示されないからといって、システムが実際に計算を複数回評価しないとは限りません。

この場合、見た目がごちゃごちゃしているという理由だけで減らすことに同意します。ただし、SQL 言語では、一般的にシステムに指示しようとしているのは、システムに指示する方法ではなく、希望する内容であることを認識しておく必要があります。それがオプティマイザーの仕事です。

于 2013-04-11T09:08:58.963 に答える
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
于 2013-04-11T09:12:24.220 に答える