Hem*_*ank 4 sql join parent-child sql-server-2008 sql-execution-plan
我显示一个包含父数据的网格,如果存在相关的子行,则需要显示图标.我的数据库在SQL Server 2008中.让我简化,我有以下两个表 -
订单(PK:ID)
文件(PK:FileID,FK:OrderID)
一个Order
可以有零个或多个与之相关的文件.该File
表有一个OrderID
包含FK引用的列Order
.现在,我正在显示一个列出所有内容的网格,Orders
我想显示一个图标图像,指示是否Order
有任何子行(文件).
这是我尝试过的一种棘手的方法,但不确定它的效率/可扩展性如何 -
SELECT DISTINCT o.ID, o.OrderNum, ...
,(CASE f.ID/f.ID WHEN 1 THEN 1 ELSE 0 END) as FilesExist
...
FROM Order AS o LEFT OUTER JOIN dbo.FileHeader as f ON f.OrderID = o.ID
Run Code Online (Sandbox Code Playgroud)
该CASE
声明似乎完全符合要求.如果存在一个或多个文件,它将返回1,否则为0.如果存在多个文件行,那么它将尝试重复Order
我添加了DISTINCT的行,我没有选择f.ID
但是f.ID/f.ID
它将是1 (它存在)和0表示null(不存在).我了解到JOIN比内联SELECT COUNT(*)
语句更好.
我已经测试过它可以工作,但我需要专家意见,需要确保这是最好的方法.这是一个非常简单的例子,但我的SELECT
陈述很复杂,因为有许多查找,并且它将是一个昂贵的提取,所以我需要确保它的可扩展性.
谢谢.
编辑#1: 总结 - 要么是内部SELECT,要有COUNT(*)
SELECT c.ClaimNo,(SELECT COUNT(*) FROM dbo.FileHeader AS f WHERE f.ClaimID = c.ID ) AS FilesHExist
FROM dbo.Claim AS c
Run Code Online (Sandbox Code Playgroud)
或者我提到过的LEFT OUTER JOIN方法.
SELECT DISTINCT c.ClaimNo, (CASE fh.ID / fh.ID WHEN 1 THEN 1 ELSE 0 END) AS FilesHExist
FROM dbo.Claim AS c LEFT OUTER JOIN dbo.FileHeader AS fh ON fh.ClaimID = c.ID
Run Code Online (Sandbox Code Playgroud)
附上查询执行计划的两个图像.请建议哪一个更好.
Erw*_*ter 13
为了选择几行,这应该是最快的:
SELECT o.ID
,o.OrderNum
,CASE WHEN EXISTS (SELECT * FROM dbo.FileHeader f WHERE f.OrderID = o.ID)
THEN 1
ELSE 0
END AS FilesHExist
FROM Order o;
Run Code Online (Sandbox Code Playgroud)
用于选择包括大部分的dbo.FileHeader
本应表现得更好:
SELECT o.ID
,o.OrderNum
,CASE WHEN f.OrderID IS NULL THEN 0 ELSE 1 END AS FilesHExist
FROM Order o
LEFT JOIN
(SELECT OrderID FROM dbo.FileHeader GROUP BY OrderID) f ON f.OrderID = o.ID
Run Code Online (Sandbox Code Playgroud)
首先分组OrderID
然后离开加入应该更便宜.最后不需要DISTINCT.
永不使用:
(CASE f.ID/f.ID WHEN 1 THEN 1 ELSE 0 END)
Run Code Online (Sandbox Code Playgroud)
它打开你到除零异常.将其替换为NULL
上面所示的支票.