如何使用sql检索不在另一个列表中的结果列表

nbnkbykc  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(407)

我有一个标准化的sql数据库。相关架构如下所示:

User
---
ID,
EmailAddress,
CategoryID

EmailLog
--------
ID,
CategoryID,
UserID,
SentOn

我需要得到一个用户的名单,还没有被发送电子邮件的特定类别今天。根据我的理解,我需要执行 LEFT JOIN . 为了做到这一点,我尝试了以下方法:

DECLARE @Today AS DATETIME;
SET @Today = GETUTCDATE();

DECLARE @CategoryID AS INT;
SET @CategoryID = 101;

SELECT
  User.ID,
  User.EmailAddress,
FROM 
  (SELECT u.ID, u.EmailAddress, u.CategoryID FROM [dbo].[User] u WHERE u.CategoryID=@CategoryID) AS User
  LEFT JOIN
  (SELECT l.CategoryID l.SentOn FROM [dbo].[EmailLog] l WHERE l.CategoryID=@CategoryID AND DAY(l.SentOn)=DAY(@Today) AND MONTH(l.SentOn)=MONTH(@Today) AND YEAR(l.SentOn)=YEAR(@Today)) AS Log
  ON User.UserID = Log.UserID
WHERE
  Log.SentOn IS NULL

我在这个问题中使用子查询是因为我的实际查询更复杂。但是,我已经验证了每个子查询都返回我期望的结果。换句话说,第一个子查询返回 User 列表。第二个子查询返回 EmailLog 今天发送的电子邮件列表。
我被困在那一部分,我检索的用户尚未发送电子邮件今天虽然。就像我想证明一个否定的观点。我错过了什么?
谢谢您!

f8rj6qna

f8rj6qna1#

我会用 not exists :

select u.*
from users u
where not exists (select 1
                  from emails e
                  where e.userid = u.id and
                        e.category = @CategoryID and
                        convert(date, e.senton) = convert(date, getutcdate())
                 );

我不知道你为什么用utc日期。我希望本地日期/时间更有意义,但这是来自您的示例代码。

toe95027

toe950272#

使用 Log.SentOn IS NULL 条件 ON Clause 而不是 Where Clause ```
SELECT
User.ID,
User.EmailAddress,
FROM
(SELECT u.ID, u.EmailAddress, u.CategoryID FROM [dbo].[User] u WHERE u.CategoryID=@CategoryID) AS User
LEFT JOIN
(SELECT l.CategoryID l.SentOn FROM [dbo].[EmailLog] l WHERE l.CategoryID=@CategoryID AND DAY(l.SentOn)=DAY(@Today) AND MONTH(l.SentOn)=MONTH(@Today) AND YEAR(l.SentOn)=YEAR(@Today)) AS Log
ON User.UserID = Log.UserID and Log.SentOn IS NULL

相关问题