LINQ中的可扩展关系划分
本文关键字:关系 划分 可扩展 LINQ | 更新日期: 2023-09-27 17:50:16
在本例中,类IcdPatient
表示Patient表(在本例中未显示)和查找表Icd
之间的多对多关系。
public class IcdPatient
{
public int PatientId { get; set; }
public int ConditionCode { get; set; }
public static List<IcdPatient> GetIcdPatientList()
{
return new List<IcdPatient>()
{
new IcdPatient { PatientId = 100, ConditionCode = 111 },
new IcdPatient { PatientId = 100, ConditionCode = 222 },
new IcdPatient { PatientId = 200, ConditionCode = 111 },
new IcdPatient { PatientId = 200, ConditionCode = 222 },
new IcdPatient { PatientId = 3, ConditionCode = 222 },
};
}
}
public class Icd
{
public int ConditionCode { get; set; }
public string ConditionName { get; set; }
public static List<Icd> GetIcdList()
{
return new List<Icd>()
{
new Icd() { ConditionCode =111, ConditionName ="Condition 1"},
new Icd() { ConditionCode =222, ConditionName ="Condition 2"},
};
}
}
我希望用户能够输入尽可能多的条件,并获得一个LINQ对象返回,告诉他们有多少PatientId
满足该查询。我想到了:
List<string> stringFilteredList = new List<string> { "Condition 1", "Condition 2" };
List<int> filteringList = new List<int> { 111,222 };
var manyToMany = IcdPatient.GetIcdPatientList();
var icdList = Icd.GetIcdList();
/*Working method without joining on the lookup table*/
var grouped = from m in manyToMany
group m by m.PatientId into g
where g.Count() == filteringList.Distinct().Count()
select new
{
PatientId = g.Key,
Count = g.Count()
};
/*End*/
foreach (var item in grouped)
{
Console.WriteLine(item.PatientId);
}
假设IcdPatient
在两个字段上都有一个复合主键,因此我们知道每一行都是唯一的。如果我们在filteringList
中找到不同数量的条目,并对PatientId
出现的次数进行计数,这意味着我们找到了所有符合所有条件的人。因为代码可能很深奥,我想做一些像将ConditionName
中的用户表设置为Icd类型,并执行相同的操作。我很少这样使用LINQ,我收集到:
List<int> filteringList = new List<int> { 111,222 };
List<string> stringFilteredList= new List<string>{"Condition 1","Condition 2" };
filteringList.Distinct();
var manyToMany = IcdPatient.GetIcdPatientList();
var icdList = Icd.GetIcdList();
/*Working method without joining on the lookup table*/
var grouped = from m in manyToMany
join i in icdList on
m.ConditionCode equals i.ConditionCode
//group m by m.PatientId into g
group new {m,i} by new { m.ConditionCode }into g
where g.Count() == filteringList.Distinct().Count()
select new
{
Condition = g.Key.ConditionCode
};
/*End*/
却不能让任何东西工作。这实际上是在我的第一个查询之上的连接,但是我没有得到我需要分组的内容。
在这种情况下,您不需要对任何内容进行分组,只需使用join和contains:
List<string> stringFilteredList= new List<string>{"Condition 1","Condition 2" };
var patients =
from icd in Icd.GetIcdList()
join patient in IcdPatient.GetIcdPatientList() on icd.ConditionCode equals patient.ConditionCode
where stringFilteredList.Contains(icd.ConditionName)
select patient.PatientId;
假设IcdPatient在两个字段上都有一个复合主键,因此我们知道每一行都是唯一的。如果我们在filteringList中找到不同数量的条目,并对PatientId出现的次数进行计数,这意味着我们已经找到了具有所有条件的所有人。因为代码可能很深奥,所以我想做一些事情,比如让ConditionName中的用户表在类型Icd中,并执行相同的操作。
我相信你是在问:
给定一个
ConditionCode
s列表,返回一个PatientId
s列表,其中每个患者具有列表中的所有病症。
在这种情况下,最简单的方法是按Id对IcdPatients表进行分组,这样我们就可以通过查看一次来了解患者的所有病情。然后我们检查我们正在寻找的每个ConditionCode
都在组中。在代码中,它看起来像:
var result = IcdPatient.GetIcdPatientList()
// group up all the objects with the same PatientId
.GroupBy(patient => patient.PatientId)
// gather the information we care about into a single object of type {int, List<int>}
.Select(patients => new {Id = patients.Key,
Conditions = patients.Select(p => p.ConditionCode)})
// get rid of the patients without every condition
.Where(conditionsByPatient =>
conditionsByPatient.Conditions.All(condition => filteringList.Contains(condition)))
.Select(conditionsByPatient => conditionsByPatient.Id);
查询格式如下:
var groupedInfo = from patient in IcdPatient.GetIcdPatientList()
group patient by patient.PatientId
into patients
select new { Id = patients.Key,
Conditions = patients.Select(patient => patient.ConditionCode) };
var resultAlt = from g in groupedInfo
where g.Conditions.All(condition => filteringList.Contains(condition))
select g.Id;
编辑:如果你也想让你的用户指定ConditionName
而不是ConditionId
,那么只需从一个转换到另一个,将结果存储在filteringList
中,像这样:
var conditionNames = // some list of names from the user
var filteringList = Icd.GetIcdList().Where(icd => conditionNames.Contains(icd.ConditionName))
.Select(icd => icd.ConditionCode);