这对我来说是一个永无止境的话题,我想知道我是否会忽视某些事情.基本上我在应用程序中使用两种类型的SQL语句:
现在,我们正在谈论针对具有数百万条记录的表的一些查询,加入另外5个具有数百万条记录的表.显然,我们几乎不想获取所有这些,这就是为什么我们有上述两种方法来限制用户查询.
案例1非常简单.我们只添加一个额外的ROWNUM过滤器:
WHERE ...
AND ROWNUM < ?
Run Code Online (Sandbox Code Playgroud)
这是非常快的,因为Oracle的CBO将考虑其执行计划考虑此过滤器,并可能应用一个FIRST_ROWS操作(类似于/*+FIRST_ROWS*/提示强制执行的操作).
然而,案例2对Oracle来说有点棘手,因为LIMIT ... OFFSET其他RDBMS中没有任何条款.因此,我们将"业务"查询嵌套在技术包装器中:
SELECT outer.* FROM (
SELECT * FROM (
SELECT inner.*, ROWNUM as RNUM, MAX(ROWNUM) OVER(PARTITION BY 1) as TOTAL_ROWS
FROM (
[... USER SORTED business query ...]
) inner
)
WHERE ROWNUM < ?
) outer
WHERE outer.RNUM > ?
Run Code Online (Sandbox Code Playgroud)
请注意,TOTAL_ROWS即使不获取所有数据,也会计算该字段以了解我们将拥有多少页.现在这个分页查询通常非常令人满意.但是时不时(正如我所说,在查询5M +记录时,可能包括非索引搜索),这运行2-3分钟.
编辑:请注意,潜在的瓶颈并不容易规避,因为在分页之前必须应用排序!
我想知道,这是最先进的模拟LIMIT ... OFFSET,包括TOTAL_ROWS在Oracle中,还是有更好的解决方案,设计会更快,例如使用ROW_NUMBER() …
Pg's Window函数的文档说:
窗口函数考虑的行是由查询的FROM子句生成的"虚拟表",由WHERE,GROUP BY和HAVING子句过滤,如果有的话.例如,任何窗口函数都看不到因为它不符合WHERE条件而被删除的行.查询可以包含多个窗口函数,这些函数通过不同的OVER子句以不同的方式对数据进行分片,但它们都作用于此虚拟表定义的相同行集合.
但是,我没有看到这一点.在我看来,选择过滤器非常靠近左边距和顶部(最后完成的事情).
=# EXPLAIN SELECT * FROM chrome_nvd.view_options where fkey_style = 303451;
QUERY PLAN
----------------------------------------------------------------------------------------------------------------------
Subquery Scan view_options (cost=2098450.26..2142926.28 rows=14825 width=180)
Filter: (view_options.fkey_style = 303451)
-> Sort (cost=2098450.26..2105862.93 rows=2965068 width=189)
Sort Key: o.sequence
-> WindowAgg (cost=1446776.02..1506077.38 rows=2965068 width=189)
-> Sort (cost=1446776.02..1454188.69 rows=2965068 width=189)
Sort Key: h.name, k.name
-> WindowAgg (cost=802514.45..854403.14 rows=2965068 width=189)
-> Sort (cost=802514.45..809927.12 rows=2965068 width=189)
Sort Key: h.name
-> Hash Join (cost=18.52..210141.57 rows=2965068 width=189)
Hash Cond: (o.fkey_opt_header = h.id)
-> …Run Code Online (Sandbox Code Playgroud) 我在SQL Server中寻找类似的东西:
SELECT TOP n WITH TIES FROM tablename
Run Code Online (Sandbox Code Playgroud)
我LIMIT在PostgreSQL中知道,但是上面存在的相同吗?我只是很好奇,因为它每次都会为我节省额外的查询.
如果我有一个Numbers属性表nums:{10, 9, 8, 8, 2}.我想做的事情如下:
SELECT nums FROM Numbers ORDER BY nums DESC LIMIT *with ties* 3
Run Code Online (Sandbox Code Playgroud)
它应该返回,{10, 9, 8, 8}因为它需要前3加上额外的,8因为它绑定另一个.
假设您(在Postgres 9.1中)有这样一个表:
date | value
Run Code Online (Sandbox Code Playgroud)
它有一些空白(我的意思是:并非每个可能的日期在最小(日期)和最大(日期)之间有它的行).
我的问题是如何聚合这些数据,以便分别处理每个一致的组(没有间隙),如下所示:
min_date | max_date | [some aggregate of "value" column]
Run Code Online (Sandbox Code Playgroud)
有什么想法怎么做?我相信这是可能的窗口功能,但是过了一段时间,试图lag()和lead()我有点卡住了.
例如,如果数据是这样的:
date | value
---------------+-------
2011-10-31 | 2
2011-11-01 | 8
2011-11-02 | 10
2012-09-13 | 1
2012-09-14 | 4
2012-09-15 | 5
2012-09-16 | 20
2012-10-30 | 10
Run Code Online (Sandbox Code Playgroud)
输出(sum作为聚合)将是:
min | max | sum
-----------+------------+-------
2011-10-31 | 2011-11-02 | 20
2012-09-13 | 2012-09-16 | 30
2012-10-30 | 2012-10-30 | 10
Run Code Online (Sandbox Code Playgroud) 这是我的问题..
Actual Auction Ammanat id
7000 500 100 228,229
7000 100 100 228,229
7000 900 100 228,229
5000 0 0 230
Run Code Online (Sandbox Code Playgroud)
我想要下面给出的结果
Actual Auction Ammanat Remaining id
7000 500 100 5550 228,229
7000 100 100 5550 228,229
7000 900 100 5550 228,229
5000 0 0 5000 230
Run Code Online (Sandbox Code Playgroud)
在这里,Remaining是(sum(auction)-actual).
我正在使用PostgreSQL.但是如果有人知道SQL Server中的解决方案,那就没问题了.
给定一个数据帧 df
id | date
---------------
1 | 2015-09-01
2 | 2015-09-01
1 | 2015-09-03
1 | 2015-09-04
2 | 2015-09-04
Run Code Online (Sandbox Code Playgroud)
我想创建一个运行计数器或索引,
从而
id | date | counter
--------------------------
1 | 2015-09-01 | 1
1 | 2015-09-03 | 2
1 | 2015-09-04 | 3
2 | 2015-09-01 | 1
2 | 2015-09-04 | 2
Run Code Online (Sandbox Code Playgroud)
这是我可以通过窗口功能实现的,例如
val w = Window.partitionBy("id").orderBy("date")
val resultDF = df.select( df("id"), rowNumber().over(w) )
Run Code Online (Sandbox Code Playgroud)
不幸的是,Spark 1.4.1不支持常规数据帧的窗口函数:
org.apache.spark.sql.AnalysisException: Could not resolve window function 'row_number'. Note that, …Run Code Online (Sandbox Code Playgroud) 我注意到,如果我使用函数调用map(),我在DataFrame上使用Window函数后,Spark会返回"Task not serializable"Exception这是我的代码:
val hc:org.apache.spark.sql.hive.HiveContext = new org.apache.spark.sql.hive.HiveContext(sc)
import hc.implicits._
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.functions._
def f():String = "test"
case class P(name:String,surname:String)
val lag_result:org.apache.spark.sql.Column = lag($"name",1).over(Window.partitionBy($"surname"))
val lista:List[P] = List(P("N1","S1"),P("N2","S2"),P("N2","S2"))
val data_frame:org.apache.spark.sql.DataFrame = hc.createDataFrame(sc.parallelize(lista))
df.withColumn("lag_result", lag_result).map(x => f)
//df.withColumn("lag_result", lag_result).map{case x => def f():String = "test";f}.collect // This works
Run Code Online (Sandbox Code Playgroud)
这是堆栈跟踪:
org.apache.spark.SparkException:org.apache.spark.util.ClosureCleaner $ .ensureSerializable(ClosureCleaner.scala:304)org.apache.spark.util.ClosureCleaner $ .org $ apache $ spark $ util中无法序列化的任务$ ClosureCleaner $$ clean(ClosureCleaner.scala:294)atg.apache.spark.util.ClosureCleaner $ .clean(ClosureCleaner.scala:122)at org.apache.spark.SparkContext.clean(SparkContext.scala:2055)at at org.apache.spark.rdd.RDD $$ anonfun $ map $ 1.apply(RDD.scala:324)at org.apache.spark.rdd.RDD $$ anonfun $ map $ …
serialization scala window-functions apache-spark apache-spark-sql
我不明白为什么ORDER BY在分析COUNT函数中使用子句时会有不同的结果.
使用一个简单的例子:
with req as
(select 1 as n, 'A' as cls
from dual
union
select 2 as n, 'A' as cls
from dual)
select req.*, count(*) over(partition by cls) as cnt from req;
Run Code Online (Sandbox Code Playgroud)
给出以下结果:
N CLS CNT
2 A 2
1 A 2
Run Code Online (Sandbox Code Playgroud)
然而,当ORDER BY在分析子句中添加一个时,结果是不同的!
with req as
(select 1 as n, 'A' as cls
from dual
union
select 2 as n, 'A' as cls
from dual)
select req.*, count(*) over(partition by …Run Code Online (Sandbox Code Playgroud) 我正在研究一个项目,我们需要计算不同行的数量.方案的简化版本包括user表,keyword表和keyword_user表.
该user表仅包括公共用户元数据,如名称等.下面列出了其他表.
keyword_user:
id
user_id
keyword_id
Run Code Online (Sandbox Code Playgroud)
关键词:
id,
description
Run Code Online (Sandbox Code Playgroud)
我想要做的是根据用户keyword_id找到最大用户数(5),同时还计算匹配行的总数.计数必须是不同的.
查询:
SELECT TOP 5 u.[id],
u.[firstname],
u.[lastname],
total = Count(*) OVER()
FROM [user] u
INNER JOIN [keyword_user] ku
ON u.[id] = ku.[user_id]
WHERE ( ku.keyword_id IN ( '5f6501ec-0a71-4067-a21d-3c5f87a76411', 'c19b95c0-8554-4bbd-9526-db8f1c4f1edf'))
AND u.id NOT IN ( '12db3001-b3b9-4626-8a02-2519102cb53a' )
Run Code Online (Sandbox Code Playgroud)
结果集:
+--------------------------------------+-----------+----------+-------+
| id | firstname | lastname | total |
+--------------------------------------+-----------+----------+-------+
| F0527AC3-747A-45A6-9CF9-B1F6C7F548F8 | Kasper | Thomsen | 3 |
| 95988F6D-9C91-4779-B6C3-3D4B4D6AE836 | Michael | …Run Code Online (Sandbox Code Playgroud) Name | Value | Timestamp
-----|-------|-----------------
One | 1 | 2016-01-01 02:00
Two | 3 | 2016-01-01 03:00
One | 2 | 2016-01-02 02:00
Two | 4 | 2016-01-03 04:00
Run Code Online (Sandbox Code Playgroud)
Name | Value | EarliestTimestamp | LatestTimestamp
-----|-------|-------------------|-----------------
One | 2 | 2016-01-01 02:00 | 2016-01-02 02:00
Two | 4 | 2016-01-01 03:00 | 2016-01-03 04:00
Run Code Online (Sandbox Code Playgroud)
我想使用ROW_NUMBER()并PARTITION BY获得最新的Name,Value但我也想要最早和最新的Timestamp价值:
SELECT
t.Name,
t.Value,
t.????????? AS EarliestTimestamp,
t.Timestamp AS LatestTimestamp …Run Code Online (Sandbox Code Playgroud) window-functions ×10
sql ×6
postgresql ×4
sql-server ×3
apache-spark ×2
scala ×2
aggregate ×1
count ×1
inner-join ×1
join ×1
oracle ×1
oracle11g ×1
performance ×1
row-number ×1
rownum ×1
sql-limit ×1
t-sql ×1
where-clause ×1