使用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
};
答案 0 :(得分:3)
您在查询中遇到的问题是,您尝试在“分组依据”之后访问“来自”变量,而您无法执行此操作。为了获得这些变量,它们必须(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
查询执行并将记录作为数组存入内存 - 然后分组和子查询会非常快。您只需要注意内存使用而不是查询执行时间。
我希望这会有所帮助。
答案 1 :(得分:0)
我通过这种方式决定使用:
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;
}