【问题标题】:Linq query for count outside joinLinq 查询外连接计数
【发布时间】:2012-10-10 11:11:52
【问题描述】:

我有两张桌子 PatientEncounterDemo 和 PatientMaster

PatientEncounterDemo:

PateientID(F.K int),
DoctorId( F.K int),
ProcedureName



PatientMaster:

PatientId(P.K identity)
PatientFirstName(varchar(50)),
PatientLastName(varchar(50)),
PatientDOB

我需要提取 PatientName(patientFirstName_+patientLastName)、patientDOB 和分配给特定患者的程序计数(一个患者可以分配许多程序)

我已经为该结果编写了 SQL 查询:

//This puts the join inside count-

select distinct  PatientFirstName+ ' ' + PatientLastName as PatientName,PatientDOB,COUNT(ProcedureName) as [Proc Count] from
(
select distinct  p.PatientFirstName,p.PatientLastName,p.PatientDOB,e.ProcedureName
from PatientMaster p,PatientEncounterDemo e 
where p.PatientId=e.PatientId and e.DoctorId=1
)as mytable group by PatientFirstName,PatientLastName,PatientDOB

但是,我正在努力通过 linq 查询来做到这一点。请提出一些建议..!!

【问题讨论】:

  • 您使用的是哪个 O/RM 工具?
  • @Steven 我没有使用任何这样的工具..我只是使用 .net 4.0 中提供的 Linq to sql(.dbml) 类
  • LINQ to SQL 是一个对象关系映射器。
  • @Steven 好的..我明白..但是这与我的问题有关吗?
  • 它是相关的,因为您的 O/RM 工具的 LINQ 支持始终是您可以使用 LINQ to Objects 执行的操作的子集,并且每个 O/RM 框架都不同。所以给出的答案可能会有所不同。

标签: linq linq-to-sql group-by grouping inner-join


【解决方案1】:

这将是从您的 SQL 到 LINQ 的(几乎)一对一映射:

var myTable = (
    from encounter in db.PatientEncounterDemos
    where encounter.Doctor.Id == 1
    let patient = encounter.Patient
    select    new 
    {
        patient.FirstName, 
        patient.LastName,         
        patient.DOB,
        encounter.ProcedureName
    })
    .Distinct();

var results =
    from item in myTable
    group item by new { item.FirstName, item.LastName, item.DOB } into g
    select new 
    { 
        PatientName = g.Key.FirstName + " " + g.Key.LastName, 
        g.Key.DOB, 
        ProcCount = g.Count() 
    };

但这会更容易理解:

var myTable = (
    from encounter in db.PatientEncounterDemos
    where encounter.Doctor.Id == 1
    select new { encounter.Patient, encounter.ProcedureName })
    .Distinct();

var results =
    from item in myTable
    group item by item into g
    select new 
    { 
        PatientName =
            g.Key.Patient.FirstName + " " + g.Key.Patient.LastName, 
        g.Key.DOB, 
        ProcCount = g.Count() 
    };

【讨论】:

    【解决方案2】:

    希望这能实现您的目标:

    var patientProcedureCounts =
        from master in PatientMasters
        select new
        {
            master.PatientId,
            PatientName = master.PatientFirstName + " " +
                master.PatientLastName,
            master.PatientDOB,
            ProcedureCount = (from demo in PatientEncounterDemos 
                where demo.PatientId == master.PatientId &&
                    demo.DoctorId == 1 
                select 1).Count()
        };
    

    这将选择所有PatientMasters,然后为PatientId 和DoctorId 选择所有PatientEncounterDemos。最后,它将使用该患者的主详细信息和演示的计数来构造一个新的匿名类型,可以像这样枚举:

    foreach(var procedureInfo in patientProcedureCounts)
    {
        Console.WriteLine("Patient {0} born on {1} had {2} procedures", 
            procedureInfo.PatientName, procedureInfo.PatientDOB, procedureInfo.ProcedureCount);
    }
    

    以下是 LINQPad 生成的 SQL,看起来与您所追求的非常接近:

    -- Region Parameters
    DECLARE @p0 NVarChar(1000) SET @p0 = ' '
    DECLARE @p1 Int SET @p1 = 1
    -- EndRegion
    SELECT [t0].[PatientId], ([t0].[PatientFirstName] + @p0) + [t0].[PatientLastName] AS [PatientName], [t0].[PatientDOB], (
        SELECT COUNT(*)
        FROM [PatientEncounterDemo] AS [t1]
        WHERE ([t1].[PatientId] = [t0].[PatientId]) AND ([t1].[DoctorId] = @p1)
        ) AS [ProcedureCount]
    FROM [PatientMaster] AS [t0]
    

    【讨论】:

    • 很抱歉这样说,但是当编译器读取 FOREACH 循环中的 patientProcedureCounts 时,此代码会出错...错误说:“System.String”类型不支持序列运算符。
    • 对@RahulRanjan 感到抱歉,我创建了一个与您的架构相同的数据库,并更新了我的查询以使其正常工作。我已经在 LINQPad 中对此进行了测试,它对我有用:)
    • 是的,我能感觉到它在你的情况下会起作用......但是是的,即使我的情况是在你的代码中进行了一些更正......我达到了我想要的......所以,非常感谢为您的答复..!!!!
    【解决方案3】:

    我已经重写了您的 SQL(希望应该可以)。这应该更容易从中生成 LINQ。

    SELECT 
        p.PatientFirstName + ' ' + p.PatientLastName as PatientName
        p.PatientDOB,
        COUNT(e.ProcudureName) AS [Proc Count]
    FROM 
        PatientMaster p
        INNER JOIN PatientEncounterDemo e ON p.PatientId = e.PatientId
    WHERE
        e.DoctorId=1
    GROUP BY
        p.PatientFirstName,
        p.PatientLastName,
        p.PatientDOB
    

    【讨论】:

    • 不。似乎你没有理解我的代码..这个编辑改变了它的意思..我首先将连接结果存储在一个临时表中,然后应用计数和分组依据该结果..当我在我的机器上检查过时,这段代码只会给出错误......!!这里
    【解决方案4】:

    最后在你所有答案的支持下,我得到了这个查询的确切结果。

    首先,我在数据库上执行内部连接以及 where 条件。

    然后我按照多列对结果进行分组,并对该组进行计数。

    我的 Linq 查询:

     var myTable = (
              from master in MyDataContext.PatientMasters
              join encounter in MyDataContext.PatientEncounterDemos
              on master.PatientId equals encounter.PatientId
              where encounter.DoctorId == doctorID
              select new { master.PatientFirstName, master.PatientLastName, master.PatientDOB, encounter.ProcedureName })
              .Distinct();
    
          var results =
              from item in myTable
              group item by new { item.PatientFirstName, item.PatientLastName, item.PatientDOB } into grp
              select new
              {
                  PatientName =
                      grp.Key.PatientFirstName + " " + grp.Key.PatientLastName,
                  grp.Key.PatientDOB,
                  ProcCount = grp.Count()
              };
    

    现在我应用 Foreach 循环将结果添加到列表中......!! 谢谢大家...!!!!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-11-08
      • 2023-03-19
      • 1970-01-01
      • 1970-01-01
      • 2015-01-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多