2010-02-17 87 views
2

我正在使用SQL Server 2005.我听说我们可以使用表变量来代替LEFT OUTER JOIN。SQL Server中的表变量

我的理解是,我们必须首先将左表中的所有值放到表变量中。然后我们必须用正确的表值更新表变量。然后从表格变量中选择。

有没有人遇到过这种方法?你能否建议一个实时的例子(带查询)?

我还没有为此写任何查询。我的问题是 - 如果有人使用了类似的方法,我想知道这个场景以及它的处理方式。我知道在某些情况下,它可能比左外连接慢。

请假设我们正在处理少于5000条记录的表格。

感谢

回答

0

我不认为这是从你的问题很清楚你想要达到什么样的? (你的桌子是什么样的,你想要什么结果)。但是你当然可以选择数据到一个表数据类型的变量中,并篡改它。这是很方便的:

DECLARE @tbl TABLE (id INT IDENTITY(1,1), userId int, foreignId int) 

INSERT INTO @tbl (userId) 
    SELECT id FROM users 
    WHERE name LIKE 'a%' 

UPDATE @tbl t 
SET 
    foreignId = (SELECT id FROM foreignTable f WHERE f.userId = t.userId) 

在那个例子我给表变量它自己的身份列,从一个源表不同。我经常发现这很有用。随心所欲地调整......再次,问题不是很清楚,但我希望这可以引导您朝着正确的方向发展......?

0

每种情况都不同,如果没有关于具体情况的完整细节,很难说它是否适合您。尽管如此,除非我有特定的功能原因 - 如果查询可以使用OUTER JOIN进行标准SELECT查询来实现,那么我不会使用表变量方法,那么我会使用该方法正如我所期望的那样效率最高。

当您希望获得中间结果集,然后对其进行一些处理然后将其返回时,您可能希望使用临时表/表变量的时间更多 - 即无法处理的那种处理用一个简单的查询来完成。

请注意表变量非常方便,但考虑到它们不保证驻留在内存中 - 它们可以可以将持久保存到tempdb(如标准临时表)。

+0

这是一个城市神话。表变量存在于tempdb中。在这里检查Q&A4:http://support.microsoft.com/kb/305977新版本仍然如此。 – 2010-02-17 13:57:10

+0

@Frank Kalis - 不是表格变量**在内存中的都市神话,事实上,他们**可以**持久化到tempdb,这取决于内存压力等因素。 – AdaTheDev 2010-02-17 15:55:35

+0

没有。它们存在于tempdb中,但它们保存的数据可能也可能不会保存到tempdb中。对于任何表(永久,临时或表变量),分配映射中至少有一个页面,磁盘上至少有一个数据页面。 SQL Server不能在缓冲池中拥有一个页面,而不在磁盘上有一个保留的对应页面。然而,表变量的数据页面可能永远不会写入tempdb,但空间仍然存在。 – 2010-02-17 20:19:16

3

它可以完成,但我不知道为什么你会想要这样做。

这真的看起来好像是在倒退。 但是,如果你想这个你自己的学习只,这里有云:

DECLARE @MainTable TABLE(
     ID INT, 
     Val FLOAT 
) 

INSERT INTO @MainTable SELECT 1, 1 
INSERT INTO @MainTable SELECT 2, 2 
INSERT INTO @MainTable SELECT 3, 3 
INSERT INTO @MainTable SELECT 4, 4 

DECLARE @LeftTable TABLE(
     ID INT, 
     MainID INT, 
     Val FLOAT 
) 

INSERT INTO @LeftTable SELECT 1, 1, 11 
INSERT INTO @LeftTable SELECT 3, 3, 33 

SELECT *, 
     mt.Val + ISNULL(lt.Val, 0) 
FROM @MainTable mt LEFT JOIN 
     @LeftTable lt ON mt.ID = lt.MainID 

DECLARE @Table TABLE(
     ID INT, 
     Val FLOAT 
) 

INSERT INTO @Table 
SELECT ID, 
     Val 
FROM @MainTable 

UPDATE @Table 
SET  Val = t.Val + lt.Val 
FROM @Table t INNER JOIN 
     @LeftTable lt ON t.ID = lt.ID 

SELECT * 
FROM @Table 
0

谢谢你,astander。

我试着用下面给出的例子。两种方法都花了19秒。不过,我想一些调整会帮助表变量更新方法变得比LEFT JOIN更快。

因为我不是高手,所以请求您的帮助。任何SQL专家准备证明它?


----请用下面的''替换“”。我不熟悉如何把代码在这个论坛...它会导致一些麻烦....

CREATE TABLE #MainTable ( 
     CustomerID INT PRIMARY KEY, 
     FirstName VARCHAR(100) 
) 


DECLARE @Count INT 
SET @Count = 0 

DECLARE @Iterator INT 
SET @Iterator = 0 

WHILE @Count <8000 
BEGIN 

    INSERT INTO #MainTable SELECT @Count, "Cust"+CONVERT(VARCHAR(10),@Count) 
    SET @Count = @Count+1 

END 

CREATE TABLE #RightTable 
( 
     OrderID INT PRIMARY KEY, 
     CustomerID INT, 
     Product VARCHAR(100) 
) 

CREATE INDEX [IDX_CustomerID] ON #RightTable (CustomerID) 

WHILE @Iterator <400000 
BEGIN 

     IF @Iterator % 2 = 0 
     BEGIN 

      INSERT INTO #RightTable SELECT @Iterator,2, "Prod"+CONVERT(VARCHAR(10),@Iterator) 
     END 
     ELSE 
     BEGIN 
      INSERT INTO #RightTable SELECT @Iterator,1, "Prod"+CONVERT(VARCHAR(10),@Iterator) 
     END 

SET @Iterator = @Iterator+1 

END 


-- Using LEFT JOIN 

SELECT mt.CustomerID,mt.FirstName,COUNT(rt.Product) [CountResult] 
FROM #MainTable mt 
     LEFT JOIN #RightTable rt ON mt.CustomerID = rt.CustomerID 
GROUP BY mt.CustomerID,mt.FirstName 


--------------------------- 



-- Using Table variable Update 


DECLARE @WorkingTableVariable TABLE 
( 
     CustomerID INT, 
     FirstName VARCHAR(100), 
     ProductCount INT 
) 

INSERT 
INTO @WorkingTableVariable (CustomerID,FirstName) 
SELECT CustomerID, FirstName FROM #MainTable 

UPDATE @WorkingTableVariable 
SET  ProductCount = [Count] 
FROM @WorkingTableVariable wt 
     INNER JOIN 
      (SELECT CustomerID,COUNT(rt.Product) AS [Count] 
      FROM #RightTable rt 
      GROUP BY CustomerID) IV ON wt.CustomerID = IV.CustomerID 

SELECT CustomerID,FirstName, ISNULL(ProductCount,0) [CountResult] FROM @WorkingTableVariable 
ORDER BY CustomerID 

-------- 

DROP TABLE #MainTable 

DROP TABLE #RightTable 

感谢 Lijo

+0

我创建了#tables,并插入了值。然后使用EXECUTION计划和Profiler,左连接执行比@TABLE插入/更新更好。持续时间较短,读取和写入。所以从我的快速分析中,我宁愿使用** LEFT JOIN **而不使用@TABLE插入/更新。 – 2010-02-17 13:37:52

+0

此外,而是修改你原来的问题。不要将答案作为问题发布给其他人。此外,他们发布的答案的评论将更容易注意他们的注意力...... – 2010-02-17 13:44:23

0

在我看来有一个理由这样做: 如果你有一个复杂的查询,有很多内连接,有一个左连接有时会遇到麻烦,因为这个查询比使用没有左连接的同一查询快几百倍。

如果您查询很多记录,并且只有很少的记录要加入到左连接中,如果将中间结果实现为表变量或临时表,则可以获得更快的结果。

但通常不需要真正更新表变量中的数据 - 您可以使用左连接查询表变量以返回结果。

...只是我的两分钱。