【问题标题】:The best way to return related data in a SQL statement在 SQL 语句中返回相关数据的最佳方式
【发布时间】:2010-06-09 13:02:22
【问题描述】:

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

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

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

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

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

感谢您的建议!

达维斯

创建表格

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)

获取结果 - 方法一

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

【问题讨论】:

  • 你应该小心地指望 IDENTITY 列总是按顺序上升。这不能保证。

标签: sql-server join subquery


【解决方案1】:

你没有在你的表上列出任何索引或 PK 信息,所以这是第一个优化,如果他们还没有的话。

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

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

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

【讨论】:

  • 感谢您的回复。我知道如果不查看这些测试表所依据的真实表和数据,很难说哪个会执行得更快。我想我更好奇是否有任何一种查询方法引发了危险信号,或者是否有人有更好的方法来进行查询。从你的回答来看,听起来两者都不像你那么可笑。再次感谢。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2016-11-11
    • 1970-01-01
    • 1970-01-01
    • 2017-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多