【问题标题】:Linq - Group by multiple tables with multiple returnsLinq - 按具有多个返回的多个表分组
【发布时间】:2011-08-03 18:48:41
【问题描述】:

使用Linq to Sql如何对下表(entidadeProdutosFornecedores)进行分组并从N个表中返回字段?

SQL 中的原始查询

SELECT  @NM_VALOR1      = MAX(ProdutosFornecedores.NM_PRECO_REPOSICAO),
                @NM_VALOR2      = MAX(ProdutosFornecedores.ID_MOEDAS_REPOSICAO),
                @ID_IMPOSTOSDESTINOS    = MAX(Fornecedores.ID_IMPOSTOSDESTINOS),
                @ID_IMPOSTOSCONFIG  = MAX(ProdutosFornecedores.ID_IMPOSTOSCONFIG),
                @ID_TABELANCMS      = MAX(ProdutosFornecedores.ID_TABELANCMS),
                @ID_FORNECEDORES    = MAX(Fornecedores.ID_FORNECEDORES),
                @CD_UF_BASE     = MAX(UnidadesFederacao.CD_UNIDADEFEDERACAO)
              FROM  ProdutosFornecedores
                INNER JOIN Fornecedores     ON Fornecedores.ID_FORNECEDORES       = ProdutosFornecedores.ID_FORNECEDORES
                INNER JOIN Municipios       ON Municipios.ID_MUNICIPIOS       = Fornecedores.ID_MUNICIPIOS
                INNER JOIN UnidadesFederacao    ON UnidadesFederacao.ID_UNIDADESFEDERACAO = Municipios.ID_UNIDADESFEDERACAO
             WHERE  ProdutosFornecedores.ID_PRODUTOS        = CAST(@CD_OBJETO1 AS INT)  AND
                ProdutosFornecedores.ID_PRODUTOSCONFIGPRECOS    = CAST(@CD_OBJETO2 AS INT)  AND
                ProdutosFornecedores.FG_STATUS          = 1
            GROUP BY
                ProdutosFornecedores.ID_PRODUTOS,
                ProdutosFornecedores.ID_PRODUTOSCONFIGPRECOS

查询转换为 Linq

var prodForn2 = from entidadeProdutosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
                                                    //Inner Join with Fornecedores
                                                    join entidadeFornecedores in ERPDAOManager.GetTable<Fornecedores>()
                                                         on entidadeProdutosFornecedores.ID_FORNECEDORES equals entidadeFornecedores.ID into tempFornecedores
                                                    from fornecedores in tempFornecedores
                                                    //Inner Join with Municipios
                                                    join entidadeMuncipios in ERPDAOManager.GetTable<Municipios>()
                                                        on fornecedores.ID_MUNICIPIOS equals entidadeMuncipios.ID into tempMunicipios
                                                    from municipios in tempMunicipios
                                                    //Inner Join with UnidadesFederacao
                                                    join entidadeUnidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
                                                        on municipios.ID_UNIDADESFEDERACAO equals entidadeUnidadesFederacao.ID into tempUnidadesFederacao
                                                    from unidadesFederacao in tempUnidadesFederacao
                                                    //Filters
                                                    where entidadeProdutosFornecedores.ID_PRODUTOS == Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1) &&
                                                          entidadeProdutosFornecedores.ID_PRODUTOSCONFIGPRECOS == Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2) &&
                                                          entidadeProdutosFornecedores.FG_STATUS == true
                                                    group entidadeProdutosFornecedores by new { entidadeProdutosFornecedores.ID_PRODUTOS, entidadeProdutosFornecedores.ID_PRODUTOSCONFIGPRECOS } into produtosFornecedores
                                                    select new
                                                    {
                                                        NM_PRECO_REPOSICAO = (decimal)produtosFornecedores.Max(item => item.NM_PRECO_REPOSICAO),
                                                        ID_MOEDAS_REPOSICAO = (int)produtosFornecedores.Max(item => item.ID_MOEDAS_REPOSICAO),
                                                        ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS, //Error: The name fornecedores does not exist in the current context
                                                        ID_IMPOSTOSCONFIG = (int)produtosFornecedores.Max(item => item.ID_IMPOSTOSCONFIG),
                                                        ID_TABELANCMS = (int)produtosFornecedores.Max(item => item.ID_TABELANCMS),
                                                        ID_FORNECEDORES = (int)fornecedores.ID, //Error: The name fornecedores does not exist in the current context
                                                        CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO //Error: The name unidadesFederacao does not exist in the current context
                                                    };

【问题讨论】:

    标签: c# .net linq linq-to-sql group-by


    【解决方案1】:

    您的查询遇到的问题是您试图在“分组依据”之后访问“来自”变量,这是您无法做到的。为了获得这些变量,它们必须 (1) 保留在分组之外或 (2) 成为分组本身的一部分。

    (1)

    var prodForn2 =
        from produtosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
        join fornecedores in ERPDAOManager.GetTable<Fornecedores>()
            on produtosFornecedores.ID_FORNECEDORES equals fornecedores.ID
        join municipios in ERPDAOManager.GetTable<Municipios>()
            on fornecedores.ID_MUNICIPIOS equals municipios.ID
        join unidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
            on municipios.ID_UNIDADESFEDERACAO equals unidadesFederacao.ID
        where produtosFornecedores.ID_PRODUTOS ==
            Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1)
        where produtosFornecedores.ID_PRODUTOSCONFIGPRECOS ==
            Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2)
        where produtosFornecedores.FG_STATUS == true
        let ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS
        let ID_FORNECEDORES = (int)fornecedores.ID
        let CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO
        group produtosFornecedores by new
        {
            ID_IMPOSTOSDESTINOS,
            ID_FORNECEDORES,
            CD_UF_BASE,
        } into gpfs1
        select new
        {
            gpfs1.Key.ID_IMPOSTOSDESTINOS,
            gpfs1.Key.ID_FORNECEDORES,
            gpfs1.Key.CD_UF_BASE,
            PRODUTOSFORNECEDORES =
                from pfs1 in gpfs1
                group pfs1 by new
                {
                    pfs1.ID_PRODUTOS,
                    pfs1.ID_PRODUTOSCONFIGPRECOS
                } into gpfs2
                select new
                {
                    NM_PRECO_REPOSICAO = (decimal)gpfs2
                        .Max(item => item.NM_PRECO_REPOSICAO),
                    ID_MOEDAS_REPOSICAO = (int)gpfs2
                        .Max(item => item.ID_MOEDAS_REPOSICAO),
                    ID_IMPOSTOSCONFIG = (int)gpfs2
                        .Max(item => item.ID_IMPOSTOSCONFIG),
                    ID_TABELANCMS = (int)gpfs2
                        .Max(item => item.ID_TABELANCMS),
                },
        };
    

    (2)

    var prodForn2 =
        from produtosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
        join fornecedores in ERPDAOManager.GetTable<Fornecedores>()
            on produtosFornecedores.ID_FORNECEDORES equals fornecedores.ID
        join municipios in ERPDAOManager.GetTable<Municipios>()
            on fornecedores.ID_MUNICIPIOS equals municipios.ID
        join unidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
            on municipios.ID_UNIDADESFEDERACAO equals unidadesFederacao.ID
        where produtosFornecedores.ID_PRODUTOS ==
            Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1)
        where produtosFornecedores.ID_PRODUTOSCONFIGPRECOS ==
            Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2)
        where produtosFornecedores.FG_STATUS == true
        let ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS
        let ID_FORNECEDORES = (int)fornecedores.ID
        let CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO
        group produtosFornecedores by new
        {
            ID_IMPOSTOSDESTINOS,
            ID_FORNECEDORES,
            CD_UF_BASE,
            produtosFornecedores.ID_PRODUTOS,
            produtosFornecedores.ID_PRODUTOSCONFIGPRECOS,
        } into gpfs
        select new
        {
            gpfs.Key.ID_IMPOSTOSDESTINOS,
            gpfs.Key.ID_FORNECEDORES,
            gpfs.Key.CD_UF_BASE,
            NM_PRECO_REPOSICAO = (decimal)gpfs.Max(item => item.NM_PRECO_REPOSICAO),
            ID_MOEDAS_REPOSICAO = (int)gpfs.Max(item => item.ID_MOEDAS_REPOSICAO),
            ID_IMPOSTOSCONFIG = (int)gpfs.Max(item => item.ID_IMPOSTOSCONFIG),
            ID_TABELANCMS = (int)gpfs.Max(item => item.ID_TABELANCMS),
        };
    

    试一试,看看哪个更适合您的需求。

    您可能还会发现性能是分组和多个最大查询的问题,因此在对结果进行分组之前将记录放入内存可能是值得的。

    var prodForn2_1 =
        from produtosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
        join fornecedores in ERPDAOManager.GetTable<Fornecedores>()
            on produtosFornecedores.ID_FORNECEDORES equals fornecedores.ID
        join municipios in ERPDAOManager.GetTable<Municipios>()
            on fornecedores.ID_MUNICIPIOS equals municipios.ID
        join unidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
            on municipios.ID_UNIDADESFEDERACAO equals unidadesFederacao.ID
        where produtosFornecedores.ID_PRODUTOS ==
            Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1)
        where produtosFornecedores.ID_PRODUTOSCONFIGPRECOS ==
            Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2)
        where produtosFornecedores.FG_STATUS == true
        let ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS
        let ID_FORNECEDORES = (int)fornecedores.ID
        let CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO
        select new
        {
            ID_IMPOSTOSDESTINOS = (int)fornecedores.ID_IMPOSTOSDESTINOS,
            ID_FORNECEDORES = (int)fornecedores.ID,
            CD_UF_BASE = (string)unidadesFederacao.CD_UNIDADEFEDERACAO,
            ID_PRODUTOS = produtosFornecedores.ID_PRODUTOS,
            ID_PRODUTOSCONFIGPRECOS = produtosFornecedores.ID_PRODUTOSCONFIGPRECOS,
            NM_PRECO_REPOSICAO = (decimal)produtosFornecedores.NM_PRECO_REPOSICAO,
            ID_MOEDAS_REPOSICAO = (int)produtosFornecedores.ID_MOEDAS_REPOSICAO,
            ID_IMPOSTOSCONFIG = (int)produtosFornecedores.ID_IMPOSTOSCONFIG,
            ID_TABELANCMS = (int)produtosFornecedores.ID_TABELANCMS,
        };
    
    var prodForn2_2 =
        from pf in prodForn2_1.ToArray()
        group ...
    

    现在您只需要使用上面的选项 (1) 或 (2) 来完成 prodForn2_2。请注意,ToArray 调用将强制执行prodForn2_1 查询并将记录作为数组带入内存 - 分组和子查询的速度非常快。您只需要注意内存使用而不是查询执行时间。

    我希望这会有所帮助。

    【讨论】:

    • 你好,谢谢。我已经对所有字段进行了分组,并且我喜欢您的选项 (2)。
    【解决方案2】:

    我通过这种方式解决了:

    var prodForn = from produtosFornecedores in ERPDAOManager.GetTable<ProdutosFornecedores>()
                                                       //Inner Join com Fornecedores
                                                       join fornecedores in ERPDAOManager.GetTable<Fornecedores>()
                                                            on produtosFornecedores.ID_FORNECEDORES equals fornecedores.ID
                                                       //Inner Join com Municipios
                                                       join municipios in ERPDAOManager.GetTable<Municipios>()
                                                           on fornecedores.ID_MUNICIPIOS equals municipios.ID
                                                       //Inner Join com UnidadesFederacao
                                                       join unidadesFederacao in ERPDAOManager.GetTable<UnidadesFederacao>()
                                                           on municipios.ID_UNIDADESFEDERACAO equals unidadesFederacao.ID
                                                       //Filtros
                                                       where produtosFornecedores.ID_PRODUTOS == Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO1) &&
                                                             produtosFornecedores.ID_PRODUTOSCONFIGPRECOS == Convert.ToInt32(objEsquemasCalculoRegras.CD_OBJETO2) &&
                                                             produtosFornecedores.FG_STATUS == true
                                                       group produtosFornecedores by new
                                                       {
                                                           ID_IMPOSTOSDESTINOS = fornecedores.ID_IMPOSTOSDESTINOS,
                                                           ID_FORNECEDORES = fornecedores.ID,
                                                           CD_UF_BASE = unidadesFederacao.CD_UNIDADEFEDERACAO,
                                                           produtosFornecedores.ID_PRODUTOS,
                                                           produtosFornecedores.ID_PRODUTOSCONFIGPRECOS
                                                       } into grpProdutosFornecedores
                                                       select new
                                                       {
                                                           grpProdutosFornecedores.Key.ID_IMPOSTOSDESTINOS,
                                                           grpProdutosFornecedores.Key.ID_FORNECEDORES,
                                                           grpProdutosFornecedores.Key.CD_UF_BASE,
                                                           NM_PRECO_REPOSICAO = (decimal)grpProdutosFornecedores.Max(item => item.NM_PRECO_REPOSICAO),
                                                           ID_MOEDAS_REPOSICAO = (int)grpProdutosFornecedores.Max(item => item.ID_MOEDAS_REPOSICAO),
                                                           ID_IMPOSTOSCONFIG = (int)grpProdutosFornecedores.Max(item => item.ID_IMPOSTOSCONFIG),
                                                           ID_TABELANCMS = (int)grpProdutosFornecedores.Max(item => item.ID_TABELANCMS)
                                                       };
    
                                        if (prodForn.Count() > 0)
                                        {
                                            NM_VALOR1 = prodForn.First().NM_PRECO_REPOSICAO;
                                            NM_VALOR2 = prodForn.First().ID_MOEDAS_REPOSICAO;
                                            ID_IMPOSTOSDESTINOS = prodForn.First().ID_IMPOSTOSDESTINOS;
                                            ID_IMPOSTOSCONFIG = prodForn.First().ID_IMPOSTOSCONFIG;
                                            ID_TABELANCMS = prodForn.First().ID_TABELANCMS;
                                            ID_FORNECEDORES = prodForn.First().ID_FORNECEDORES;
                                            CD_UF_BASE = prodForn.First().CD_UF_BASE;
                                        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多