在SQL语句中返回相关数据的最佳方法

时间:2010-06-09 13:02:23

标签: sql-server join subquery

我有一个关于回到多对多关系表另一侧相关表中的数据的最佳方法的问题。

我的第一个方法使用连接来返回数据,但由于关系表中有多个匹配的行,我不得不使用TOP 1来获得单行结果。

我的第二种方法使用子查询来获取数据,但这感觉不对。

所以,我的问题是,哪个是首选方法,还是有更好的方法?

创建测试表,插入数据和运行两个查询所需的脚本如下所示。

感谢您的建议!

Darvis

创建表格

DECLARE @TableA TABLE (
[A_ID] [int] IDENTITY(1,1) NOT NULL,
[Description] [varchar](50) NULL)

DECLARE @TableB TABLE (
[B_ID] [int] IDENTITY(1,1) NOT NULL,
[A_ID] [int] NOT NULL,
[Description] [varchar](50) NOT NULL)

DECLARE @TableC TABLE (
[C_ID] [int] IDENTITY(1,1) NOT NULL,
[Description] [varchar](50) NOT NULL)

DECLARE @TableB_C TABLE (
[B_ID] [int] NOT NULL,
[C_ID] [int] NOT NULL)

插入测试数据

INSERT INTO @TableA VALUES('A-One')
INSERT INTO @TableA VALUES('A-Two')
INSERT INTO @TableA VALUES('A-Three')

INSERT INTO @TableB (A_ID, Description) VALUES(1,'B-One')
INSERT INTO @TableB (A_ID, Description) VALUES(1,'B-Two')
INSERT INTO @TableB (A_ID, Description) VALUES(1,'B-Three')
INSERT INTO @TableB (A_ID, Description) VALUES(2,'B-Four')
INSERT INTO @TableB (A_ID, Description) VALUES(2,'B-Five')
INSERT INTO @TableB (A_ID, Description) VALUES(3,'B-Six')

INSERT INTO @TableC VALUES('C-One')
INSERT INTO @TableC VALUES('C-Two')
INSERT INTO @TableC VALUES('C-Three')

INSERT INTO @TableB_C (B_ID, C_ID) VALUES(1, 1)
INSERT INTO @TableB_C (B_ID, C_ID) VALUES(2, 1)
INSERT INTO @TableB_C (B_ID, C_ID) VALUES(3, 1)

获取结果 - 方法1

SELECT TOP 1 C.*, A.Description
FROM @TableC C
JOIN @TableB_C BC ON BC.C_ID = C.C_ID
JOIN @TableB B ON B.B_ID = BC.B_ID
JOIN @TableA A ON B.A_ID = A.A_ID
WHERE C.C_ID = 1

获取结果 - 方法2

SELECT C.*,               
(SELECT A.Description
FROM @TableA A
WHERE EXISTS (SELECT * 
      FROM @TableB_C BC
      JOIN @TableB B ON B.B_ID = BC.B_ID
      WHERE BC.C_ID = C.C_ID AND B.A_ID = A.A_ID))
FROM @TableC C
WHERE C.C_ID = 1

2 个答案:

答案 0 :(得分:0)

您没有在表格中列出任何索引或PK信息,因此这是第一个要进行的优化,如果它们已经没有那些。

根据有限的测试数据无法告诉您,优化器将根据您的实际数据使用统计数据来确定索引使用情况和最佳查询执行计划。

您可以在SQL Server Management Studio查询窗口中使用SET SHOWPLAN_ALL ON查看每个查询的执行计划,然后比较它们以查看哪个更好。

要快速检查,请尝试以下操作:运行SET SHOWPLAN_ALL ON然后运行方法1查询,查看第一行的TotalSubtreeCost。然后,运行方法2查询,再次查看第一行的TotalSubtreeCost。哪个查询的值较低?如果您想进行更详细的评估,可以查看StmtText,EstimateIO和EstimateCPU,以及任何其他列。

答案 1 :(得分:0)

如果要在一个表中的行与另一个表中的多个行相关的情况下获得单行,则需要定义要使用哪些行。一旦定义了那么你就可以编写一个查询来获取该行。

在你的情况下,无论你通过@TableB和@TableB_C采用哪种方式,所有C行都指向所有相同的A行,但这肯定不会通过你拥有的模式强制执行。