2017-10-06 57 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             
相关问题