我有一个左外连接(下面)按预期返回结果.我需要将"右"表的结果限制为"第一次"命中.我能以某种方式这样做吗?目前,我得到两个表中每个记录的结果,我只想看左边表中的一个结果(项目),无论我在右表(照片)中有多少结果.
var query = from i in db.items join p in db.photos on i.id equals p.item_id into tempPhoto from tp in tempPhoto.DefaultIfEmpty() orderby i.date descending select new { itemName = i.name, itemID = i.id, id = i.id, photoID = tp.PhotoID.ToString() }; GridView1.DataSource = query; GridView1.DataBind();
Amy B.. 64
这将为您完成这项工作.
from i in db.items let p = db.photos.Where(p2 => i.id == p2.item_id).FirstOrDefault() orderby i.date descending select new { itemName = i.name, itemID = i.id, id = i.id, photoID = p == null ? null : p.PhotoID.ToString(); }
当我针对自己的模型生成它时,我得到了这个sql(并且在投影中没有名称和第二个id列).
SELECT [t0].[Id] AS [Id], CONVERT(NVarChar,( SELECT [t2].[PhotoId] FROM ( SELECT TOP (1) [t1].[PhotoId] FROM [dbo].[Photos] AS [t1] WHERE [t1].[Item_Id] = ([t0].[Id]) ) AS [t2] )) AS [PhotoId] FROM [dbo].[Items] AS [t0] ORDER BY [t0].[Id] DESC
当我询问该计划时,它显示子查询是通过此连接实现的:
Nick Berardi.. 5
您要对表进行分组。最好的方法是:
var query = from i in db.items join p in (from p in db.photos group p by p.item_id into gp where gp.Count() > 0 select new { item_id = g.Key, Photo = g.First() }) on i.id equals p.item_id into tempPhoto from tp in tempPhoto.DefaultIfEmpty() orderby i.date descending select new { itemName = i.name, itemID = i.id, id = i.id, photoID = tp.Photo.PhotoID.ToString() };
编辑:这是艾米B说话。我之所以这样做,是因为尼克要求我这样做。尼克,请根据需要修改或删除此部分。
生成的SQL很大。通过参数传入int 0(与计数进行比较)。
SELECT [t0].X AS [id], CONVERT(NVarChar(MAX),( SELECT [t6].Y FROM ( SELECT TOP (1) [t5].Y FROM [dbo].[Photos] AS [t5] WHERE (([t4].Y IS NULL) AND ([t5].Y IS NULL)) OR (([t4].Y IS NOT NULL) AND ([t5].Y IS NOT NULL) AND ([t4].Y = [t5].Y)) ) AS [t6] )) AS [PhotoId] FROM [dbo].[Items] AS [t0] CROSS APPLY (( SELECT NULL AS [EMPTY] ) AS [t1] OUTER APPLY ( SELECT [t3].Y FROM ( SELECT COUNT(*) AS [value], [t2].Y FROM [dbo].[Photos] AS [t2] GROUP BY [t2].Y ) AS [t3] WHERE (([t0].X) = [t3].Y) AND ([t3].[value] > @p0) ) AS [t4]) ORDER BY [t0].Z DESC
执行计划揭示了三个左连接。至少一个是微不足道的,不应计入(它为零)。这里有足够的复杂性,我无法明确指出效率方面的任何问题。它可能运行得很好。
这将为您完成这项工作.
from i in db.items let p = db.photos.Where(p2 => i.id == p2.item_id).FirstOrDefault() orderby i.date descending select new { itemName = i.name, itemID = i.id, id = i.id, photoID = p == null ? null : p.PhotoID.ToString(); }
当我针对自己的模型生成它时,我得到了这个sql(并且在投影中没有名称和第二个id列).
SELECT [t0].[Id] AS [Id], CONVERT(NVarChar,( SELECT [t2].[PhotoId] FROM ( SELECT TOP (1) [t1].[PhotoId] FROM [dbo].[Photos] AS [t1] WHERE [t1].[Item_Id] = ([t0].[Id]) ) AS [t2] )) AS [PhotoId] FROM [dbo].[Items] AS [t0] ORDER BY [t0].[Id] DESC
当我询问该计划时,它显示子查询是通过此连接实现的:
您要对表进行分组。最好的方法是:
var query = from i in db.items join p in (from p in db.photos group p by p.item_id into gp where gp.Count() > 0 select new { item_id = g.Key, Photo = g.First() }) on i.id equals p.item_id into tempPhoto from tp in tempPhoto.DefaultIfEmpty() orderby i.date descending select new { itemName = i.name, itemID = i.id, id = i.id, photoID = tp.Photo.PhotoID.ToString() };
编辑:这是艾米B说话。我之所以这样做,是因为尼克要求我这样做。尼克,请根据需要修改或删除此部分。
生成的SQL很大。通过参数传入int 0(与计数进行比较)。
SELECT [t0].X AS [id], CONVERT(NVarChar(MAX),( SELECT [t6].Y FROM ( SELECT TOP (1) [t5].Y FROM [dbo].[Photos] AS [t5] WHERE (([t4].Y IS NULL) AND ([t5].Y IS NULL)) OR (([t4].Y IS NOT NULL) AND ([t5].Y IS NOT NULL) AND ([t4].Y = [t5].Y)) ) AS [t6] )) AS [PhotoId] FROM [dbo].[Items] AS [t0] CROSS APPLY (( SELECT NULL AS [EMPTY] ) AS [t1] OUTER APPLY ( SELECT [t3].Y FROM ( SELECT COUNT(*) AS [value], [t2].Y FROM [dbo].[Photos] AS [t2] GROUP BY [t2].Y ) AS [t3] WHERE (([t0].X) = [t3].Y) AND ([t3].[value] > @p0) ) AS [t4]) ORDER BY [t0].Z DESC
执行计划揭示了三个左连接。至少一个是微不足道的,不应计入(它为零)。这里有足够的复杂性,我无法明确指出效率方面的任何问题。它可能运行得很好。