从另一个表中获取具有不同属性组合的行

时间:2012-05-12 16:06:15

标签: c# sql-server-2008 tsql

我在做什么:

我正在编写一个C#应用程序,它将帮助员工处理电子邮件。我有一个带邮件的数据库(MS SQL Server 2008 Express)。一个表包含邮件本身(每行包含msgId,发件人,收件人,主题,正文等列),另一个表包含员工如何处理邮件的数据 - 每当电子邮件分配了一些属性时,新行将属性保存到第二个表。第二个表包含列:msgId,forTeam,notForTeam,processedByTeam。只要员工将消息标记为与其团队相关,就会在forTeam列中使用TEAMXX值保存一行。每当员工对电子邮件执行其他操作时,具有TEAMXX值的行将保存在processedByTeam列中。

我正在尝试收到以下值的电子邮件:
forTeam:'TEAM01'
notForTeam:与'TEAM01'不同的一切 processedByTeam:与'TEAM01'

不同的一切

我使用MailAssignments表在Mails表上进行LEFT JOIN,然后在WHERE之后我将上述条件放在上面。结果应该显示已分配给TEAM01但尚未由该团队的员工处理的消息。



问题:

我无法让SQL查询正常工作。条件的任何组合都将返回额外的行(例如,当我想省略那些时,属性为notForTeam ='TEAM01')或者由于某种原因给我一个错误,即datetime的格式不正确(我按接收时间排序电子邮件) )。

示例查询:

SELECT TOP 30 Mails.* 
FROM Mails 
LEFT JOIN MailAssignments 
ON Mails.msgId = MailAssignments.msgId 
WHERE
(MailAssignments.forTeam='TEAM01') 
AND (MailAssignments.notForTeam<>'TEAM01' OR MailAssignments.notForTeam IS NULL) 
AND (MailAssignments.processedByTeam<>'TEAM01' OR MailAssignments.processedByTeam IS NULL)
ORDER BY Mails.sortingTime DESC

即使我将WHERE之前(和ORDER BY之前)的条件减少到(MailAssignments.notForTeam<>'TEAM01')进行测试,我仍然会因某种原因得到错误。

我错过了什么或做错了什么?



UPDATE:

似乎(MailAssignments.notForTeam<>'TEAM01')以某种方式导致问题。其他一切正常(也是等号是OK:MailAssignments.notForTeam ='TEAM01')但是当我添加notForTeam<>条件时,我得到了错误的日期时间错误(WTF?:/)

System.Data.SqlTypes.SqlTypeException:SqlDateTime溢出。必须在1/1/1753 12:00:00 AM和12/31/9999 11:59:59 PM之间。



更新 - 示例:

table with mails ("Mails"):
msgId sender  subject body  received (sortingTime)
53    x@x.com test    test  2012-05-11 11:00
54    b@b.com test2   test2 2012-05-10 10:00
55    h@h.com blah    blah  2012-05-11 12:00
56    t@t.com dfgg    dfgg  2012-05-11 12:30


table with assignments ("MailAssignments"):
msgId forTeam notForTeam  processedByTeam
54    null    TEAM02      null            - this means TEAM02 hid the mail from their view
54    TEAM01  null        null            - this means TEAM01 assigned the mail to them
54    null    null        TEAM01          - TEAM01 has processed the mail

53    TEAM01  null        null            - invisible to other teams
53    null    TEAM01      null            - invisible for TEAM01 (and also for others because of the above)

56    TEAM01  null        null
56    null    null        TEAM01          - mail processed by TEAM01

55    TEAM02  null        null            - assigned to TEAM02 but not processed yet


Now, I want my C# app to have a view which will display mails as "This Team's", ie.:
1. mail 54 was first hidden for TEAM02 - should be invisible for them
2. mail 54 was assigned to TEAM01 - should be now visible for them in "This Team's" view
3. mail 54 was processed by TEAM01 - should be now invisible in "This Team's" view

4. mail 53 was assigned to TEAM01 - should visible in their "This Team's" view (and ONLY for them)
5. mail 53 was hidden for TEAM01 - should be invisible to TEAM01 (and for anyone else because of prev. action)

6. mail 56 was assigned to TEAM01 - should be now visible only to TEAM01 in "This Team's"
7. mail 56 was processed by TEAM01 - should be now invisible for TEAM01 in "This Team's"

So, with the present data in both tables, finally, TEAM02 for example should see in their "This Team's" view only:
mail 55

2 个答案:

答案 0 :(得分:2)

Select TOP 30 *
From Mails As M
Where Exists    (
                Select 1
                From MailAssignments As MA1
                Where MA1.msgid = M.msgid
                    And MA1.forTeam = 'TEAM01'
                Except
                Select 1
                From MailAssignments As MA1
                Where MA1.msgid = M.msgid
                    And ( MA1.processedByTeam = 'TEAM01' 
                         Or MA1.notForTeam = 'TEAM01' )
                )
Order By M.received Desc

SQL Fiddle版。

拥有样本数据和模式会让世界变得与众不同。错过的是每个MailAssignments行有多个Mails行。因此,当您说要排除notForTeam = 'TEAM01'的行时,真正意味着排除任何具有该值的关联msgid。我已更新我的查询以适应该请求。您可能怀疑的Except子句会消除第一个查询中存在的第二个查询中的任何匹配值。由于我在两个查询中都使用常量,如果第二个查询返回给定msgid的任何行,它将使整个Exists查询不返回任何行并排除msg。

也就是说,TEAM01没有行,因为:

MsgId = 54 is excluded because according to Rule #3, messages 
    that were processed by the team should be excluded.
MsgId = 53 is excluded because notForTeam = 'TEAM01' (Rule #5)
MsgId = 56 is excluded because processedBy = 'TEAM01' (Rule #7)
MsgId = 55 is excluded because forTeam = 'TEAM02'

答案 1 :(得分:0)

尝试:

WHERE
MailAssignments.forTeam='TEAM01'
AND MailAssignments.notForTeam<>'TEAM01'
AND MailAssignments.processedByTeam<>'TEAM01'
ORDER BY Mails.sortingTime DESC

这应该可以解决问题