2010-02-17 89 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

在我看來有一個理由這樣做: 如果你有一個複雜的查詢,有很多內連接,有一個左連接有時會遇到麻煩,因爲這個查詢比使用沒有左連接的同一查詢快幾百倍。

如果您查詢很多記錄,並且只有很少的記錄要加入到左連接中,如果將中間結果實現爲表變量或臨時表,則可以獲得更快的結果。

但通常不需要真正更新表變量中的數據 - 您可以使用左連接查詢表變量以返回結果。

...只是我的兩分錢。