Linq 将子查询关联到多个列上的相同 table

Linq correlated subquery to same table on multiple columns

我已经查看了与相关子查询相关的其他几个问题,但我仍然不清楚如何完成我需要的。我正在使用 Entity Framework 和 C#,并且有一个名为 STEWARDSHIP 的 table,包含以下列:

我需要确定 SITE_ID、VISIT_DATE、VISIT_TYPE_ID 的相同组合不止一次存在的情况,因为它可能代表最终用户错误地输入了重复条目,然后我需要报告这些条目的详细信息。在 SQL 中,我将通过加入 GROUP BY/HAVING 的临时结果来做到这一点,如下所示:

SELECT * FROM stewardship AS s2,
(SELECT site_id, visit_type_id, CAST(visit_date AS DATE) AS visit_date
    FROM stewardship
    GROUP BY site_id, visit_type_id, CAST(visit_date AS DATE)
    HAVING COUNT(*) > 1) AS s
WHERE s2.site_id = s.site_id
AND s2.visit_type_id = s.visit_type_id
AND CAST(s2.visit_date AS DATE) = s.visit_date

在 Linq 中完成此任务的最佳方法是什么?

它与您已有的非常相似。

from s in context.stewardships
group s by new {s.site_id, s.visit_type_id, visit_date} into g
where g.Count() > 1
select g;

这将为您提供具有相似价值观的管理团队。您可以 "flatten" 之后使用 SelectMany 获得这些结果,但您可能会发现它们对于分组处理更有用。

请注意,您可能需要使用 SqlFunctions 或其他工具来执行与日期转换等效的操作。

由于您对 应该 性能更高的不同方法持开放态度,这里是新的 SQL 来实现我认为您想要的。

select distinct s1.*
from stewardship s1
    inner join stewardship s2 on 
        s1.stewardship_id <> s2.stewardship_id and
        s1.site_id = s2.site_id and
        s1.visit_type_id = s2.visit_type_id and
        cast(s1.visit_date as date) = cast(s2.visit_date as date)
order by s1.site_id, s1.visit_type_id

现在,要将其转换为 LINQ,您可以使用以下语句。

var duplicates = (
    from s in Stewardships
    join s2 in Stewardships
        on new { s.Site_id, s.Visit_type_id, s.Visit_date.Date } equals new { s2.Site_id, s2.Visit_type_id, s2.Visit_date.Date }
    where s.Stewardship_id != s2.Stewardship_id
    select s)
.Distinct()
.OrderBy(s => s.Site_id)
    .ThenBy(s => s.Visit_type_id)

请注意,除了等值连接之外,您不能使用任何表达式连接,因此我不得不将非等值连接(通过 PK 确保我们的匹配项不在同一记录上)放在 where 表达式中。您也可以通过 Except() 扩展方法使用 lambda 来完成此操作。

顺序是为了结果的可读性并匹配上面的 SQL 语句。

希望对您有所帮助!