【发布时间】:2011-12-22 13:21:09
【问题描述】:
我显示一个带有父数据的网格,如果它存在相关的子行,则需要显示图标。 我的数据库在 SQL Server 2008 中。让我简化一下,我有以下两个表 -
订单(PK : ID)
文件(PK:FileID,FK:OrderID)
Order 可以有零个或多个与之相关的文件。 File 表有一个列 OrderID,其中包含对 Order 的 FK 引用。现在,我正在显示一个列出所有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
CASE 语句似乎可以按要求完美运行。如果存在一个或多个文件,它将返回 1,否则返回 0。如果存在多个文件行,那么它将尝试重复 Order 行,我已为其添加了 DISTINCT 并且我没有选择 @987654332 @ 但 f.ID/f.ID 将是 1(它存在)和 0 代表 null(不存在)。我了解到 JOIN 比内联 SELECT COUNT(*) 语句更好。
我已经测试过并且它有效,但我需要专家意见并且需要确保这是最好的方法。这是一个非常简单的例子,但我的 SELECT 语句很复杂,因为有很多查找,而且它的获取成本很高,所以我需要确保它的可扩展性。
谢谢。
编辑#1: 总而言之 - 要么是 internal SELECT 带有 COUNT(*)
SELECT c.ClaimNo,(SELECT COUNT(*) FROM dbo.FileHeader AS f WHERE f.ClaimID = c.ID ) AS FilesHExist
FROM dbo.Claim AS c
或我提到的 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
附上两张查询执行计划的图片。请建议哪个更好。
【问题讨论】:
-
您使用的是什么类型的 SQL?此外,
File的左外连接似乎会产生NULL值,这是否由dbo.FileHeader以ISNULL()处理?你的意思是f.ID/o.ID吗?显然f.ID/f.ID会总是 == 1? -
我的数据库在 SQL Server 2008 中。我的想法是在 JOIN 产生 NULL 值时设置为 0。因此,如果 f.ID/f.ID 存在,则始终为 1,如果为 NULL,则始终为 0。这就是 CASE 语句所暗示的 - 它无需包含任何中间 SELECT * 或 COUNT 语句即可达到目的。
-
如果您得到答案,请标记为是
-
附加查询执行计划。请让我知道您的最终裁决。
标签: sql sql-server-2008 parent-child sql-execution-plan join