linq 如何获取在另一个表中没有特定记录的记录

mv1qrgav  于 2022-12-06  发布在  其他
关注(0)|答案(3)|浏览(165)

请考虑以下表格:
用户名:

UserId      Name       LastName
--------------------------------
User1       Name1        LName1
User2       Name2        LName2
User3       Name3        LName3
User4       Name4        LName4

和用户登录日志:

UserId       LogDate      Status
--------------------------------
User1       2022-01-01      1 <--For Successful Login
User1       2022-01-02      0 <--For UnSuccessful Login
User2       2022-01-02      1
User4       2022-02-02      1
User4       2022-03-02      0
User4       2022-05-02      1
User4       2022-05-10      0
User5       2022-05-10      0

不,我想找到那些在特定时间段内(例如上个月1天)没有登录的用户。从另一个Angular 来看,我想找到那些在特定时间段内至少有一次Successful登录的用户。
我编写了一些查询,但无法检查至少包含一个Successful登录日志的排除记录。这是Linq查询的SQL版本:

select * 
from Users aa left join Login_Log bb on aa.UserId = bb.UserId
where (bb.LogDate >= DATEADD(month, -1, getdate()) and bb.LogDate <= getdate()) and bb.Status is null
eh57zj3b

eh57zj3b1#

LogedInUsers CTE包含至少有一次成功登录的用户。则最终结果为不在CTE中的用户:

WITH LogedInUsers
AS (SELECT DISTINCT bb.UserId
    FROM Login_Log bb
    WHERE bb.LogDate >= DATEADD(MONTH, -1, GETDATE())
          AND bb.LogDate <= GETDATE()
          AND bb.Status = 1
   )
SELECT aa.*
FROM Users aa
    LEFT JOIN LogedInUsers liu ON aa.UserId = liu.UserId
    WHERE liu.UserId IS NULL;
qhhrdooz

qhhrdooz2#

我不希望在特定持续时间内至少有一次成功登录的用户登录。

DateTime startPeriod = ...
DateTime endPeriod = ...
IEnumerable<UserLogin> userLogins == ...
IEnumerable<User> Users = ...

要求给予在startPeriod和endPeriod之间(含)的时间段内未成功登录的所有用户。

首先,我们获取在此期间至少成功登录一次的所有用户的UserId

IEnumerable<UserId> idsOfSuccessfulUserLoginDuringPeriod = userLogins

    // only the succesful UserLogins during period:
    .Where(userLogin => userLogin.Status == 1
           && startPeriod <= userLogin.LogDate
           && userLogin.LogData <= endPeriod)

    // select only the UserIds
    .Select(userLogin => userLogin.UserId)

    // and remove duplicates
    .Distinct();

换句话说:从所有登录尝试中,仅保留该期间内的成功尝试。从剩余的用户登录中选择用户ID,并删除重复项。
如果userId是引用类型,则不能在Distinct中使用默认的相等比较器,必须提供按值比较的引用类型。
现在删除在以下时间段内成功登录的所有用户:

IEnumerable<User> usersThatHadNoSuccessfulLoginDuringPeriod = users.

    .Where(user => !idsOfSuccessfulUserLoginDuringPeriod.Contains(user.UserId));

换句话说:要获取在此期间未成功登录的所有用户,请从所有用户开始,并仅保留在此期间成功登录的用户的UserId集合中UserId为NOT的用户。
当然,你可以用一个很大的LINQ语句来写,这不会提高效率,我确信这会降低可读性。
简单的问候!

cgh8pdjw

cgh8pdjw3#

您可以在“使用者”表格中选取其ID在上个月没有成功登入的使用者。以下是linq的解决方案:

var dormientUsers = from u in users 
                    where !(from ul in userLoginLogs
                            where ul.Status && ul.LogDate >= DateTime.Now.AddMonths(-8) && ul.LogDate <= DateTime.Now
                            select ul.UserId)  
                            .Contains(u.UserId)
                    select u;

该解决方案采用以下定义:

public class User{

    public string UserId { get; set; }
    public string Name { get; set; }
    public string LastName { get; set; }
    
}

public class UserLoginLog{
    
    public string UserId { get; set; }
    public DateTime LogDate { get; set; }
    public bool Status { get; set; }
    
}

usersuserLoginLogs分别是UserUserLoginLog的列表。例如,根据问题中的示例数据:

IList<User> users = new List<User>() { 
    new User() { UserId = "User1", Name = "Name1", LastName = "LName1"} ,
    new User() { UserId = "User2", Name = "Name2", LastName = "LName2"} ,
    new User() { UserId = "User3", Name = "Name3", LastName = "LName3"} ,
    new User() { UserId = "User4", Name = "Name4", LastName = "LName4"} ,
    new User() { UserId = "User5", Name = "Name5", LastName = "LName5"} ,
};

IList<UserLoginLog> userLoginLogs = new List<UserLoginLog>() { 
    new UserLoginLog() { UserId = "User1", LogDate = new DateTime(2022, 1, 1), Status = true} ,
    new UserLoginLog() { UserId = "User2", LogDate = new DateTime(2022, 1, 2), Status = false} ,
    new UserLoginLog() { UserId = "User4", LogDate = new DateTime(2022, 1, 2), Status = true} ,
    new UserLoginLog() { UserId = "User4", LogDate = new DateTime(2022, 1, 2), Status = true} ,
    new UserLoginLog() { UserId = "User1", LogDate = new DateTime(2022, 1, 2), Status = false} ,
    new UserLoginLog() { UserId = "User4", LogDate = new DateTime(2022, 1, 2), Status = true} ,
    new UserLoginLog() { UserId = "User4", LogDate = new DateTime(2022, 5, 10), Status = false} ,
    new UserLoginLog() { UserId = "User5", LogDate = new DateTime(2022, 5, 10), Status = false} ,
        };

相关问题