我有一個sql視圖,我正在使用它來檢索數據。我們可以說它有一大串產品,它們與購買它們的顧客有關。每個產品的視圖應只返回一行,而不管它鏈接到多少客戶。我正在使用row_number函數來實現這一點。 (這個例子被簡化,一般情況會查詢那裏應該只爲這是返回行的一些列X的每個唯一值一個返回行並不重要)重構使用row_number()返回具有唯一列值的行的tsql視圖
CREATE VIEW productView AS
SELECT * FROM
(SELECT
Row_number() OVER(PARTITION BY products.Id ORDER BY products.Id) AS product_numbering,
customer.Id
//various other columns
FROM products
LEFT OUTER JOIN customer ON customer.productId = prodcut.Id
//various other joins
) as temp
WHERE temp.prodcut_numbering = 1
現在讓我們說,該視圖中的總行數爲〜100萬,並且從productView運行select *需要10秒。在產品ID = 10的productView中執行查詢(如select *)需要相同的時間。我相信這是因爲查詢得到這個評估
SELECT * FROM
(SELECT
Row_number() OVER(PARTITION BY products.Id ORDER BY products.Id) AS product_numbering,
customer.Id
//various other columns
FROM products
LEFT OUTER JOIN customer ON customer.productId = prodcut.Id
//various other joins
) as temp
WHERE prodcut_numbering = 1 and prodcut.Id = 10
我認爲這是導致內部子查詢每次完整評估。理想情況下,我想沿着以下方向使用一些東西
SELECT
Row_number() OVER(PARTITION BY products.productID ORDER BY products.productID) AS product_numbering,
customer.id
//various other columns
FROM products
LEFT OUTER JOIN customer ON customer.productId = prodcut.Id
//various other joins
WHERE prodcut_numbering = 1
但是這似乎不被允許。有什麼辦法可以做類似的事嗎?
編輯 -
多次試驗之後,我相信我有實際的問題是如何強制加入到只返回1行。我嘗試使用outer apply,如下所示。一些示例代碼。
CREATE TABLE Products (id int not null PRIMARY KEY)
CREATE TABLE Customers (
id int not null PRIMARY KEY,
productId int not null,
value varchar(20) NOT NULL)
declare @count int = 1
while @count <= 150000
begin
insert into Customers (id, productID, value)
values (@count,@count/2, 'Value ' + cast(@count/2 as varchar))
insert into Products (id)
values (@count)
SET @count = @count + 1
end
CREATE NONCLUSTERED INDEX productId ON Customers (productID ASC)
通過上述樣本集,下面
select * from Products
outer apply (select top 1 *
from Customers
where Products.id = Customers.productID) Customers
了 '讓一切' 查詢時間1000毫秒〜運行。添加明確的條件:
select * from Products
outer apply (select top 1 *
from Customers
where Products.id = Customers.productID) Customers
where Customers.value = 'Value 45872'
需要一定的時間。對於相當簡單的查詢來說,這1000毫秒已經太多了,並且在添加其他類似的連接時會以錯誤的方式擴展(向上)。
你需要實際客戶的詳細信息或者只是存在或只是一個客戶ID?子查詢是評估的,因爲「10」事先不知道。你正在問第十排。因此,我的第一個問題關於期望的輸出 – gbn
真的很好的觀察 - SQL無法將視圖過濾器應用到子查詢中。你真的需要視圖的靈活性嗎?如果您使用SPROC或帶有「已定義」過濾器的表值函數(在您的示例中爲ProductID),則可以將過濾器構建到子查詢中。而在PARTITION BY和FILTER相同的情況下(ProductId),根本不需要PARTITION--所以SELECT TOP 1應該足夠了。 – StuartLC
我確實需要實際的客戶詳細信息(如果不存在,則爲空值),而不僅僅是一個的存在。我也必須使用視圖,重構檢索數據的應用程序是不可能的。 – John