用于查找已准备好的报告的电子邮件的SQL查询

时间:2013-12-23 02:49:55

标签: c# sql sql-server email

我有两张表EmailQueueReportQueueEmailQueue包含所有需要发送的电子邮件,ReportQueue包含所有需要生成的报告。 ReportQueue有一列ReportStatus,用于显示报告是否已准备就绪。 N是新的,C已完成并准备就绪。

虽然在我的C#应用​​程序中发送电子邮件之前,我很容易检查所有报告是否已准备好发送电子邮件,但我希望不必首先拉出所有行并检查报告是否已准备就绪。我想知道是否有任何方式使用SQL只获取所有相应报告已准备好的电子邮件或没有报告的电子邮件?谢谢我对SQL比较陌生。

如果我通过C#这样做,我通常会做类似

的事情
foreach (var email in emails)
{
    if (reports.Where(x => x.EmailQueueId == email.EmailQueueId).All(x => x.ReportStatus == "C") ||
        reports.Where(x => x.EmailQueueId == email.EmailQueueId) == null)
    {
        //Send Email out
    }
}

数据库示例结构:

ReportQueue
+--------------+--------------------------------+--------------+
| EmailQueueId |           ReportPath           | ReportStatus |
+--------------+--------------------------------+--------------+
|            1 | null                           | N            |
|            1 | C:\reports\report.xls          | C            |
|            3 | C:\reports\reportForThings.xls | C            |
+--------------+--------------------------------+--------------+

EmailQueue
+--------------+-------------+
| EmailQueueId | EmailStatus |
+--------------+-------------+
|            1 | N           |
|            2 | N           |
|            3 | N           |
+--------------+-------------+

在上面的示例中,电子邮件ID 2和3已准备好发送,但1不是因为其中一个报告尚未生成。

编辑:期望的结果可能只是一张准备好发送的电子邮件表,所以基于上面的例子,返回的表将是

+--------------+-------------+
| EmailQueueId | EmailStatus |
+--------------+-------------+
|            2 | N           |
|            3 | N           |
+--------------+-------------+

2 个答案:

答案 0 :(得分:2)

SELECT Email.*
FROM EmailQueue As Email
LEFT JOIN (SELECT EmailQueueId,SUM(RStatus) As Tt
            FROM (SELECT EmailQueueId,
                CASE 
                    WHEN reportStatus = 'N' THEN 0
                    WHEN reportStatus = 'C' THEN NULL
                END  As RStatus
            FROM ReportQueue
                  ) A
        GROUP BY EmailQueueId
        ) AS Report ON(Email.EmailQueueId = Report.EmailQueueId)
WHERE Report.Tt IS  NULL

答案 1 :(得分:1)

SELECT e.EmailQueueId, e.EmailStatus
FROM EmailQueue e
LEFT JOIN ReportQueue r ON e.EmailQueueId = r.EmailQueueId
GROUP BY e.EmailQueueId, e.EmailStatus
HAVING SUM(CASE WHEN r.ReportStatus IS NOT NULL AND 
                     r.ReportStatus <> 'C' 
                THEN 1 ELSE 0 END) = 0 ;

这是 SQL Fiddle演示

第二个选项

SELECT e.*
FROM EmailQueue e
LEFT JOIN (SELECT COUNT(ReportStatus) num, EmailQueueId 
           FROM ReportQueue
           WHERE ReportStatus <> 'C'
           GROUP BY EmailQueueId) tr
     ON e.EmailQueueId = tr.EmailQueueId
WHERE COALESCE(tr.num, 0) = 0;
第二个选项

SQL Fiddle