2017-10-06 104 views
2
類別

記錄要選擇N個記錄每一個類可以做:如何有效地查詢牛每

SELECT category, category_id, value FROM 
(
    SELECT category, value, row_number() OVER (PARTITION by category) as category_id 
    FROM myTable 
) 
WHERE category_id < N; 

內部的選擇將第一個分區每個類別中的記錄,並指定每個類別中的每個記錄稱爲CATEGORY_ID的ID。 然後,外部查詢將使用category_id來限制每個類別查詢的記錄數。

這是在BIG表上效率非常低,因爲它將通過將ID分配給所有記錄,即使我們只對每個類別的N個記錄感興趣。

以下不適用於我正在使用的sql引擎 - 不知道它是否適用於任何引擎。

SELECT category, value, row_number() OVER (PARTITION by category) as category_id 
FROM myTable 
WHERE category_id < N 

有沒有人知道有更好的時間複雜性來實現這一目標的其他方法?

更多的想法:

時間譜對上面的查詢下面的算法可能會提供更多的見解,以查詢幕後如何運行:

1. SELECT DISTINCT(category) FROM myTable 
    2. FOREACH category SELECT N rows 

更多信息: 我的數據是物理分區category,能夠明確利用這將是有用的

+2

即使你的第二個查詢將一些RDBMS工作,執行計劃很可能是相同的第一個 – Lamak

+0

你可以嘗試派生錶轉儲到#TEMP並創建索引,然後查詢它 – LONG

+1

用您正在使用的數據庫標記您的問題。 –

回答

4

作爲@拉馬克mentio在註釋中,你不能避免對錶中的所有行進行排序,但不能說明原因。需要進行排序以確定結果集應該被劃分的不同類別,並且在每個分區內沒有明確排序的情況下,行號很容易被確定爲類別排序的副作用。

查詢如何在「幕後」運行,或者如果使用正確的術語,它的執行計劃由索引的存在(或不存在)決定,這可能有助於避免該類別排序。如果您在(category, value)上有覆蓋索引,並且在結果中需要其他任何列,那麼您的查詢將運行得更加有效。

在這一種情況下,簡化算法可能看起來更像是這樣的:

  1. 閱讀包含所有必需的列,包括行號預分類記載,從指數。
  2. 放棄行號大於n的記錄。

你的 「理想」 查詢

SELECT category, value, row_number() OVER (PARTITION by category) as 
category_id FROM myTable WHERE category_id < N 

可能不會在任何SQL數據庫上運行,因爲SELECT名單後的WHERE子句謂詞處理,所以category_id不明當謂詞被評估時。

+0

在我的情況下,表格是通過'category'在hdfs上進行物理分區的,db2似乎沒有足夠的智能來利用它。 – r2d2oid

+1

您可能想要更詳細地描述您的軟件堆棧。 DB2本身並不知道或關心hdfs。你在談論BigSQL嗎,可能是? – mustaccio

+0

是的,後端是ibm'bigsql' – r2d2oid

0

rownumber的其他方法,但我也有性能懷疑。我同意@mustaccio。我的例子取5行...

select distinct f1.category, f3.*    
from yourtable f1       
inner join lateral           
(               
select f2.value from yourtable f2    
where f2.category=f1.category 
fetch first 5 rows only          
) f3 on 1=1             
相關問題