Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 在SQL语句中返回相关数据的最佳方法_Sql Server_Join_Subquery - Fatal编程技术网

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

Sql server 在SQL语句中返回相关数据的最佳方法,sql-server,join,subquery,Sql Server,Join,Subquery,我有一个问题,关于返回多对多关系表另一侧的相关表中的一段数据的最佳方法 我的第一个方法使用联接返回数据,但是因为关系表中有多个匹配行,所以我必须使用前1来获得单行结果 我的第二个方法使用子查询来获取数据,但这感觉不太对劲 所以,我的问题是,哪种方法是首选的,还是有更好的方法 下面是创建测试表、插入数据和运行这两个查询所需的脚本 谢谢你的建议 达维斯 创建表格 DECLARE @TableA TABLE ( [A_ID] [int] IDENTITY(1,1) NOT NULL, [Descrip

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

我的第一个方法使用联接返回数据,但是因为关系表中有多个匹配行,所以我必须使用前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
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
插入测试数据

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
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
获取结果-方法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
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

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
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

您没有在表中列出任何索引或PK信息,因此,如果表中还没有索引或PK信息,那么这是要进行的第一次优化

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

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


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

您没有在表中列出任何索引或PK信息,因此这是第一个要进行的优化,如果表中还没有索引或PK信息的话

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

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


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

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


在您的例子中,所有的C行恰好指向所有相同的一行,无论您通过@TableB和@TableB_C走哪条路,但这肯定不是通过您现有的模式强制执行的。

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


在您的例子中,无论您通过@TableB和@TableB_C走哪条路,所有C行都恰好指向同一行,但这肯定不是通过您已有的模式强制实现的。

感谢您的回复。我知道,如果不查看这些测试表所模拟的实际表和数据,很难说哪个会执行得更快。我想我更好奇的是,这两种查询方法中是否有一种会引起危险,或者是否有人有更好的方法进行查询。从你的反应来看,两人都没有因为可笑而对你大发雷霆。再次感谢,谢谢你的回复。我知道,如果不查看这些测试表所模拟的实际表和数据,很难说哪个会执行得更快。我想我更好奇的是,这两种查询方法中是否有一种会引起危险,或者是否有人有更好的方法进行查询。从你的反应来看,两人都没有因为可笑而对你大发雷霆。再次感谢。您应该小心地指望标识列始终按顺序上升。这是不能保证的。您应该小心地指望标识列始终按顺序递增。这不是保证。