use*_*076 12 c# sql-server entity-framework
我有以下表结构:
dbo.Owner
OwnerID OwnerName
1 John
2 Marie
3 Alex
Run Code Online (Sandbox Code Playgroud)
和dbo.Pet
PetID PetTag Status OwnerID
1 A341 Active 1
2 A342 Inactive 1
3 A343 Active 2
4 A345 Active 2
Run Code Online (Sandbox Code Playgroud)
我需要归还所有只有活动宠物或没有宠物的主人.
所以在上面这个例子中,我需要返回所有者2(所有宠物都有效)和所有者3(没有宠物)
我将使用Entity Framework在C#中提取数据,但是纯SQL就足够了.
这是我到目前为止所提出的:
select mi.* from Owner o
join Pet p
on o.OwnerID= p.OwnerID
where o.Status='Active'
union select * from Owner
where OwnerID not in (select OwnerID from Pet)
Run Code Online (Sandbox Code Playgroud)
现在,上面的这个查询有效但它包含OwnerID = 1.而且我想知道是否有一种方法可以在没有union的1个查询中执行此操作.
如果您的唯一值为Status"活动"和"非活动",则实际上可以简化查询.当你说:
我需要归还所有只有活动宠物或没有宠物的主人.
这将实际转化为:
我需要归还所有没有非活动宠物的主人.
然后您的查询变得更容易.
在实体框架查询中:
owners = context.Owners
.Where(o => !o.Pets.Any(p => p.Status == "Inactive"))
.ToList();
Run Code Online (Sandbox Code Playgroud)
由此生成的SQL查询是:
SELECT
[Extent1].[OwnerID] AS [OwnerID],
[Extent1].[OwnerName] AS [OwnerName]
FROM [dbo].[Owners] AS [Extent1]
WHERE NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Pets] AS [Extent2]
WHERE ([Extent1].[OwnerID] = [Extent2].[OwnerID]) AND (N'Inactive' = [Extent2].[Status])
)
Run Code Online (Sandbox Code Playgroud)
或者删除杂乱:
SELECT
OwnerID,
OwnerName
FROM Owners o
WHERE NOT EXISTS (SELECT
1
FROM Pets p
WHERE (o.OwnerID = p.OwnerID AND p.Status = 'Inactive')
)
Run Code Online (Sandbox Code Playgroud)
如果您有更多Status的值,您可以使用(Entity Framework):
owners = context.Owners
.Where(o => o.Pets.Any(p => p.Status == "Active") || !o.Pets.Any())
.Where(o => !o.Pets.Any(p => p.Status == "Inactive" /* || p.Status == "Lost" and any other values */))
.ToList();
Run Code Online (Sandbox Code Playgroud)
这将生成SQL查询:
SELECT
[Extent1].[OwnerID] AS [OwnerID],
[Extent1].[OwnerName] AS [OwnerName]
FROM [dbo].[Owners] AS [Extent1]
WHERE (( EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Pets] AS [Extent2]
WHERE ([Extent1].[OwnerID] = [Extent2].[OwnerID]) AND (N'Active' = [Extent2].[Status])
)) OR ( NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Pets] AS [Extent3]
WHERE [Extent1].[OwnerID] = [Extent3].[OwnerID]
))) AND ( NOT EXISTS (SELECT
1 AS [C1]
FROM [dbo].[Pets] AS [Extent4]
WHERE ([Extent1].[OwnerID] = [Extent4].[OwnerID]) AND (N'Inactive' = [Extent4].[Status])
))
Run Code Online (Sandbox Code Playgroud)
你想测试它的性能,可能有更好的方法,但它会给你想要的结果.它确实假设你有外键/导航属性.
小智 1
select DISTINCT
o.Id
FROM Owner o
LEFT JOIN Pet p ON o.OwnerID= p.OwnerID
where p.Status='Active' OR p.OwnerID IS NULL
Run Code Online (Sandbox Code Playgroud)