如何缩短TSQL中的长UNION ALL查询

如何缩短TSQL中的长UNION ALL查询,tsql,logic,Tsql,Logic,我需要缩短这个查询,虽然我非常擅长SQL,但我仍在学习 SELECT 'doejoh', DATETIME, [Recipient-Address], [Message-Subject], [Sender-Address] FROM dbo.Logs WHERE LEFT([Recipient-Address], 6) IN ('doejoh') UNION ALL SELEC

我需要缩短这个查询,虽然我非常擅长SQL,但我仍在学习

    SELECT
        'doejoh',
        DATETIME,
        [Recipient-Address], [Message-Subject], [Sender-Address] 
    FROM
        dbo.Logs 
    WHERE
        LEFT([Recipient-Address], 6) IN ('doejoh') 
UNION ALL 
    SELECT
        'doejoh',
        DATETIME,
        [Recipient-Address], [Message-Subject], [Sender-Address] 
    FROM
        dbo.Logs 
    WHERE
        LEFT([Recipient-Address], 10) IN ('john.doe@g') 
UNION ALL 
    SELECT
        'doejoh',
        DATETIME,
        [Recipient-Address], [Message-Subject], [Sender-Address] 
    FROM
        dbo.Logs 
    WHERE
            LEFT([Sender-Address], 6) IN ('doejoh') 
    UNION ALL 
    SELECT
        'doejoh',
        DATETIME,
        [Recipient-Address], [Message-Subject], [Sender-Address] 
    FROM
        dbo.Logs 
    WHERE
            LEFT([Sender-Address], 10) IN ('john.doe@g')
    ORDER BY
        DateTime
我必须使用这个联合,因为在同一个表中,每个用户及其电子邮件地址有4种不同的可能性。也就是说,我有30个用户,所以在整个查询中30x4将是120个组。第一列必须是用户名的原因是我在Crystal报表中使用了该列

我只是想为我的查询创建一些逻辑,以缩短查询时间,同时将每个用户分配到相应的第一列

编辑以添加

虽然这将缩短我的查询,但我仍然需要30个工会:

SELECT
   'doejoh',
   DATETIME,
   [Recipient-Address], [Message-Subject], [Sender-Address] 
FROM
   dbo.Logs 
WHERE
   LEFT([Recipient-Address], 6) IN ('doejoh') OR
   LEFT([Recipient-Address], 10) IN ('john.doe@g') OR
   LEFT([Sender-Address], 6) IN ('doejoh') OR
   LEFT([Sender-Address], 10) IN ('john.doe@g')
ORDER BY
   DateTime
因为下一个用户将与上一个用户联合:

UNION ALL 
SELECT
   'doejan',
   DATETIME,
   [Recipient-Address], [Message-Subject], [Sender-Address] 
FROM
   dbo.Logs 
WHERE
   LEFT([Recipient-Address], 6) IN ('doejan') OR
   LEFT([Recipient-Address], 10) IN ('jane.doe@g') OR
   LEFT([Sender-Address], 6) IN ('doejan') OR
   LEFT([Sender-Address], 10) IN ('jan.doe@g')

诸如此类。。。还有更短的方法吗?

您应该将查询重写为:

SELECT
   'doejoh',
   DATETIME,
   [Recipient-Address], [Message-Subject], [Sender-Address] 
FROM
   dbo.Logs 
WHERE
   LEFT([Recipient-Address], 6) IN ('doejoh') OR
   LEFT([Recipient-Address], 10) IN ('john.doe@g') OR
   LEFT([Sender-Address], 6) IN ('doejoh') OR
   LEFT([Sender-Address], 10) IN ('john.doe@g')
ORDER BY
   DateTime
在选择方面应该是一样的,只是更快更容易理解,我认为


Marc

您应该将查询改写为:

SELECT
   'doejoh',
   DATETIME,
   [Recipient-Address], [Message-Subject], [Sender-Address] 
FROM
   dbo.Logs 
WHERE
   LEFT([Recipient-Address], 6) IN ('doejoh') OR
   LEFT([Recipient-Address], 10) IN ('john.doe@g') OR
   LEFT([Sender-Address], 6) IN ('doejoh') OR
   LEFT([Sender-Address], 10) IN ('john.doe@g')
ORDER BY
   DateTime
在选择方面应该是一样的,只是更快更容易理解,我认为

马克,你就不能用

SELECT
    'doejoh',
    DATETIME,
    [Recipient-Address], [Message-Subject], [Sender-Address] 
FROM
    dbo.Logs 
 WHERE
    (LEFT([Recipient-Address], 10) IN ('john.doe@g'))
or  (LEFT([Recipient-Address], 6) IN ('doejoh') )
or  ( LEFT([Sender-Address], 10) IN ('john.doe@g'))
or  (LEFT([Sender-Address], 6) IN ('doejoh') )
你就不能用

SELECT
    'doejoh',
    DATETIME,
    [Recipient-Address], [Message-Subject], [Sender-Address] 
FROM
    dbo.Logs 
 WHERE
    (LEFT([Recipient-Address], 10) IN ('john.doe@g'))
or  (LEFT([Recipient-Address], 6) IN ('doejoh') )
or  ( LEFT([Sender-Address], 10) IN ('john.doe@g'))
or  (LEFT([Sender-Address], 6) IN ('doejoh') )

创建一个映射表并连接到它

差不多

select user_name, DateTime .... 
from Logs
join Users on 
   LEFT([Recipient-Address], 6) IN (user_name) OR
   LEFT([Recipient-Address], 10) IN (user_email) OR
   LEFT([Sender-Address], 6) IN (user_name) OR
   LEFT([Sender-Address], 10) IN (user_email)

创建一个映射表并连接到它

差不多

select user_name, DateTime .... 
from Logs
join Users on 
   LEFT([Recipient-Address], 6) IN (user_name) OR
   LEFT([Recipient-Address], 10) IN (user_email) OR
   LEFT([Sender-Address], 6) IN (user_name) OR
   LEFT([Sender-Address], 10) IN (user_email)

有没有这样的事情行不通的原因

CREATE TABLE #TempNames
(
    shortname nvarchar(6),
    longname nvarchar(10)
)

INSERT INTO #TempNames (shortname, longname) VALUES('doejoh', 'john.doe@g')
INSERT INTO #TempNames (shortname, longname) VALUES('doejan', 'jan.doe@g')
INSERT INTO #TempNames (shortname, longname) VALUES('smibob', 'bob.smith@g')

SELECT
    #TempName.shortname,
    DATETIME,
    [Recipient-Address], [Message-Subject], [Sender-Address]
FROM
    dbo.Logs
INNER JOIN
    #TempNames
ON
    LEFT([Recipient-Address], 6) = #TempNames.shortname
OR
    LEFT([Recipient-Address], 10) = #TempNames.longname
OR
    LEFT([Sender-Address], 6) = #TempNames.shortname
OR
    LEFT([Sender-Address], 10) = #TempNames.longname

有没有这样的事情行不通的原因

CREATE TABLE #TempNames
(
    shortname nvarchar(6),
    longname nvarchar(10)
)

INSERT INTO #TempNames (shortname, longname) VALUES('doejoh', 'john.doe@g')
INSERT INTO #TempNames (shortname, longname) VALUES('doejan', 'jan.doe@g')
INSERT INTO #TempNames (shortname, longname) VALUES('smibob', 'bob.smith@g')

SELECT
    #TempName.shortname,
    DATETIME,
    [Recipient-Address], [Message-Subject], [Sender-Address]
FROM
    dbo.Logs
INNER JOIN
    #TempNames
ON
    LEFT([Recipient-Address], 6) = #TempNames.shortname
OR
    LEFT([Recipient-Address], 10) = #TempNames.longname
OR
    LEFT([Sender-Address], 6) = #TempNames.shortname
OR
    LEFT([Sender-Address], 10) = #TempNames.longname

创建一个包含30人电子邮件地址的表。 表:电子邮件 栏目:短6、长10、电子邮件

然后只使用1个union all

Select Emails.short6, Logs.DateTime, Logs.[Recipient-Address], Logs.[Message-Subject], Logs.[Sender-Address]
From Emails JOIN Log on Emails.email = Log.[Recipient-Address]
Where LEFT([Recipient-Address], 6) = Emails.short6 
or LEFT([Recipient-Address], 10) = Emails.long10

union all

Select Emails.short6, Logs.DateTime, Logs.[Recipient-Address], Logs.[Message-Subject], Logs.[Sender-Address]
From Emails JOIN Log on Emails.email = Log.[Sender-Address]
Where LEFT([Sender-Address], 6) = Emails.short6 
or LEFT([Sender-Address], 10) = Emails.long10

创建一个包含30人电子邮件地址的表。 表:电子邮件 栏目:短6、长10、电子邮件

然后只使用1个union all

Select Emails.short6, Logs.DateTime, Logs.[Recipient-Address], Logs.[Message-Subject], Logs.[Sender-Address]
From Emails JOIN Log on Emails.email = Log.[Recipient-Address]
Where LEFT([Recipient-Address], 6) = Emails.short6 
or LEFT([Recipient-Address], 10) = Emails.long10

union all

Select Emails.short6, Logs.DateTime, Logs.[Recipient-Address], Logs.[Message-Subject], Logs.[Sender-Address]
From Emails JOIN Log on Emails.email = Log.[Sender-Address]
Where LEFT([Sender-Address], 6) = Emails.short6 
or LEFT([Sender-Address], 10) = Emails.long10


我仍然会有30个工会使用上面的代码。我一直在努力避免,为什么?您应该能够删除您的联合,并将其替换为WHERE子句中的OR语句,这在IMHOPlus中可读性更高,如果您需要检查两个用户,您可以将每个WHERE子句扩展为:LEFT[收件人地址],'doejoh'中的6,','doejan'等->无联合:-但是,如果您要使用这么多的用户ID进行搜索,那么最好创建一个单独的表来保存所有用户ID,然后按照其他人的建议加入该搜索表down@marc_s因为第一列将为所有john doe添加“doejoh”,为所有jane doe添加“doejan”,等等,为我的所有用户添加。我不会把所有的位置都赋给一个值“doejoh”…我仍然会有30个联合使用上面的代码。我一直在努力避免,为什么?您应该能够删除您的联合,并将其替换为WHERE子句中的OR语句,这在IMHOPlus中可读性更高,如果您需要检查两个用户,您可以将每个WHERE子句扩展为:LEFT[收件人地址],'doejoh'中的6,','doejan'等->无联合:-但是,如果您要使用这么多的用户ID进行搜索,那么最好创建一个单独的表来保存所有用户ID,然后按照其他人的建议加入该搜索表down@marc_s因为第一列将为所有john doe添加“doejoh”,为所有jane doe添加“doejan”,等等,为我的所有用户添加。我并没有将所有的Where都赋给一个值“doejoh”…如果我的回答正确,您将返回一个包含5列的结果集,其中发件人地址或收件人地址包含“doejoh”或“john”。doe@g'作为前6个和10个字符,分别?是否有一个SenderID或RecipientID或另一个数字标识符可以用来与字符串模式匹配相对应?@Russ Cam-它必须是字符串匹配。如果我有正确的答案,您希望返回一个包含5列的结果集,其中发件人地址或收件人地址包含“doejoh”或“john”。doe@g'作为前6个和10个字符,分别?是否有一个SenderID或RecipientID或另一个数字标识符可以用来与字符串模式匹配相对应?@Russ Cam-它必须是字符串匹配。感谢Robin Day为我提供了一些有用的东西。今天我学到了一些新东西,对此我感激不尽……感谢罗宾·戴为我提供了一些有用的东西。我今天学到了一些新东西,对此我感激不尽。。。