sql是一種冗長的語言,其中最冗長的特性之一是視窗函式.
在.最近遇到的堆疊溢位問題,有人要求計算某一特定日期的時間序列中的第乙個值和最後乙個值之間的差額:
輸入
volume tstamp
---------------------------
29011 2012-12-28 09:00:00
28701 2012-12-28 10:00:00
28830 2012-12-28 11:00:00
28353 2012-12-28 12:00:00
28642 2012-12-28 13:00:00
28583 2012-12-28 14:00:00
28800 2012-12-29 09:00:00
28751 2012-12-29 10:00:00
28670 2012-12-29 11:00:00
28621 2012-12-29 12:00:00
28599 2012-12-29 13:00:00
28278 2012-12-29 14:00:00期望輸出
first last difference date
------------------------------------
29011 28583 428 2012-12-28
28800 28278 522 2012-12-29請注意,值和時間戳級數可能不相關。所以,沒有一條規定如果
timestamp2 > timestamp1
然後value2 < value1
。否則,這個簡單的查詢就能工作(使用postgresql語法):
select
max(volume) as first,
min(volume) as last,
max(volume) - min(volume) as difference,
cast(tstamp as date) as date
from t
group by cast(tstamp as date);有幾種方法可以在不涉及視窗函式的組中找到第乙個和最後乙個值。例如:
有關各種方法的更多細節可以在這裡找到:
最好的方法是使用像oracle這樣的聚合函式,但是很少有資料庫具有這種功能。所以,我們將使用first_value
和last_value
視窗函式:
select distinct
first_value(volume) over (
partition by cast(tstamp as date)
order by tstamp
rows between unbounded preceding and unbounded following
) as first,
last_value(volume) over (
partition by cast(tstamp as date)
order by tstamp
rows between unbounded preceding and unbounded following
) as last,
first_value(volume) over (
partition by cast(tstamp as date)
order by tstamp
rows between unbounded preceding and unbounded following
)
- last_value(volume) over (
partition by cast(tstamp as date)
order by tstamp
rows between unbounded preceding and unbounded following
) as diff,
cast(tstamp as date) as date
from t
order by cast(tstamp as date)哎呀。
看上去不太容易讀。但它將產生正確的結果。當然,我們可以包裝列的定義。first
和last
在派生表中,但這仍然會給我們留下兩次視窗定義的重複:
partition by cast(tstamp as date)
order by tstamp
rows between unbounded preceding and unbounded following幸運的是,至少有3個資料庫實現了sql標準。
window
條款:
上面的查詢可以重構為這個查詢:
select distinct
first_value(volume) over w as first,
last_value(volume) over w as last,
first_value(volume) over w
- last_value(volume) over w as diff,
cast(tstamp as date) as date
from t
window w as (
partition by cast(tstamp as date)
order by tstamp
rows between unbounded preceding and unbounded following
)
order by cast(tstamp as date)請注意,如何使用視窗規範來指定視窗名稱,就像定義公共表示式一樣(
with
條款):
window
as ()我不僅可以重用整個規範,還可以根據部分規範構建規範,並且只重用部分規範。我以前的查詢可以這樣重寫:
select distinct
first_value(volume) over w3 as first,
last_value(volume) over w3 as last,
first_value(volume) over w3
- last_value(volume) over w3 as diff,
cast(tstamp as date) as date
from t
window
w1 as (partition by cast(tstamp as date)),
w2 as (w1 order by tstamp),
w3 as (w2 rows between unbounded preceding
and unbounded following)
order by cast(tstamp as date)每個視窗規範可以從頭建立,也可以基於先前定義的視窗規範。注在引用視窗定義時也是如此。如果我想重用
partition by
條款和order by
子句,但請更改frame
條款(rows ...
),那麼我就可以這樣寫了:
select distinct
first_value(volume) over (
w2 rows between unbounded preceding and current row
) as first,
last_value(volume) over (
w2 rows between current row and unbounded following
) as last,
first_value(volume) over (
w2 rows unbounded preceding
) - last_value(volume) over (
w2 rows between 1 preceding and unbounded following
) as diff,
cast(tstamp as date) as date
from t
window
w1 as (partition by cast(tstamp as date)),
w2 as (w1 order by tstamp)
order by cast(tstamp as date)
SQL 過濾資料(使用WHERE子句)
只檢索所需要資料需要指定搜尋條件,搜尋條件也稱為過濾條件。在select語句中,資料根據where子句中指定的搜尋條件進行過濾,即where 子句用於過濾記錄,也就是where 子句用於提取那些滿足指定標準的記錄。where子句在表名 from子句 之後給出。where子句不僅用於select語法,...
如何優雅地拼SQL的in子句
in 語句如何優雅拼接 name list 在專案中,經常會碰到這樣的場景,要按 name list 獲取這些name對應的記錄,比如要獲取 king,jones,ford 對應的記錄,顯然想到的是使用 in 子句,比如 select id from employee where emp name ...
如何使用 Xmonad,Linux的平鋪視窗管理器
平鋪視窗管理器讓你在螢幕上自動排列 windows,使你的生活變得更加輕鬆。xmonad是乙個很容易開始的最簡單的方法 你只需要學習一些鍵盤快捷鍵。xmonad也是高度可以配置的。儘管如這裡,如果不希望 它不能從框中工作,就不必觸控配置檔案。預設情況下,xmonad不包括應用程式啟動器。你可能還需要...