简体   繁体   English

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

[英]How to shorten long UNION ALL query in TSQL

I need to shorten this query and while I'm pretty good at SQL, I'm still learning. 我需要缩短此查询,虽然我非常擅长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

I have to use this union, because in the same table, there are 4 different possibilities for each user and their email address. 我必须使用此联合,因为在同一表中,每个用户及其电子邮件地址有4种不同的可能性。 That being said, I have 30 users, so 30x4 would be 120 groups in this entire query. 就是说,我有30个用户,所以30x4将是整个查询中的120个组。 The reason the first column has to be the username is because I'm using that column in a Crystal Report. 第一列必须是用户名的原因是因为我在Crystal Report中使用了该列。

I'm just looking to create some logic for my query that will shorten it down, while at the same time, "assigning" each user to their appropriate first column. 我只是想为查询创建一些逻辑,以缩短查询时间,同时将每个用户“分配”到其相应的第一列。

Edited to add 编辑添加

While this will shorten my query, I'll still have to have 30 unions: 虽然这会缩短查询时间,但我仍然必须拥有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

Because the next user would be unioned to the previous one: 因为下一个用户将被合并到上一个用户:

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')

And so on and so forth... any shorter way? 等等等等……还有什么更短的方法吗?

You should rewrite your query as: 您应该将查询重写为:

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

SHould be the same in terms of selection, just a bit faster and easier to understand, I think. 我认为选择方面应该相同,只是更快,更容易理解。

Marc

Is there a reason something like this won't work? 是否有这样的原因不起作用?

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 a mapping table and join to it. 创建一个映射表并连接到它。

eg. 例如。 something like 就像是

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)

Can't you use just... 你不能只使用...

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') )

Create a table with the email address of the 30 people. 创建一个包含30个人的电子邮件地址的表格。 Table: Emails Columns: short6, long10, email 表:电子邮件列:short6,long10,电子邮件

then using only 1 union all 然后仅使用1个并集

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM