tags:

views:

187

answers:

5

I need to shorten this query and while I'm pretty good at SQL, I'm still learning.

    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. That being said, I have 30 users, so 30x4 would be 120 groups in this entire query. The reason the first column has to be the username is because I'm using that column in a 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:

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?

+5  A: 

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

marc_s
I'll still have 30 Unions using your code above. I was trying to avoid that.
GregD
why? you should be able to remove your unions and replace them with "OR" statements in the WHERE clause which is a lot more readable IMHO
marc_s
Plus, if you need to check for two users, you can extend each of your WHERE clauses to be:LEFT([Recipient-Address], 6) IN ('doejoh', 'doejan')and so forth --> no more UNIONS :-)
marc_s
but then again, if you're using that many user ID to search for, you might be better off creating a separate table to hold them all and then join against that search table (as others have suggested further on down)
marc_s
@marc_s Because the first column will have 'doejoh' for all of john doe, 'doejan' for all of jane doe, etc., for all of my users. I'm not assigning all of wheres to one value 'doejoh'..
GregD
Good point - I'd say, go with Robin Day's suggestion of a temporary table to hold the short and long name you wish you select, and then do a JOIN from your "Logs" table to that temporary table.
marc_s
+1  A: 

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') )
James Curran
+2  A: 

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)
Sam Saffron
+4  A: 

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
Robin Day
Thank you Robin Day for providing me something that works. I learned something new today and I can't thank you enough for that...
GregD
+1  A: 

Create a table with the email address of the 30 people. Table: Emails Columns: short6, long10, email

then using only 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