日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java关闭窗口函数_2016年将是Java终于拥有窗口函数的那一年!

發布時間:2023/12/3 java 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java关闭窗口函数_2016年将是Java终于拥有窗口函数的那一年! 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

java關閉窗口函數

你沒聽錯。 到目前為止,出色的窗口功能是SQL獨有的功能。 甚至復雜的函數式編程語言似乎仍然缺少這種漂亮的功能(如果我錯了,請糾正我,Haskell伙計們)。

我們撰寫了許多有關窗口函數的博客文章,并在諸如以下文章中向我們的受眾宣講:

  • 可能最酷SQL功能:窗口函數
  • 使用此整潔的窗口函數技巧來計算時間序列中的時差
  • 如何在SQL中查找最長的連續事件系列
  • 不要錯過帶有FIRST_VALUE(),LAST_VALUE(),LEAD()和LAG()的超凡SQL能力
  • ROW_NUMBER(),RANK()和DENSE_RANK()之間的區別

我最喜歡的窗口函數示例用例之一是運行總計 。 即從以下銀行帳戶交易表中獲取:

| ID | VALUE_DATE | AMOUNT | |------|------------|--------| | 9997 | 2014-03-18 | 99.17 | | 9981 | 2014-03-16 | 71.44 | | 9979 | 2014-03-16 | -94.60 | | 9977 | 2014-03-16 | -6.96 | | 9971 | 2014-03-15 | -65.95 |

…到此,并計算出余額:

| ID | VALUE_DATE | AMOUNT | BALANCE | |------|------------|--------|----------| | 9997 | 2014-03-18 | 99.17 | 19985.81 | | 9981 | 2014-03-16 | 71.44 | 19886.64 | | 9979 | 2014-03-16 | -94.60 | 19815.20 | | 9977 | 2014-03-16 | -6.96 | 19909.80 | | 9971 | 2014-03-15 | -65.95 | 19916.76 |

對于SQL,這是小菜一碟。 觀察SUM(t.amount) OVER(...)的用法:

SELECTt.*,t.current_balance - NVL(SUM(t.amount) OVER (PARTITION BY t.account_idORDER BY t.value_date DESC,t.id DESCROWS BETWEEN UNBOUNDED PRECEDINGAND 1 PRECEDING),0) AS balance FROM v_transactions t WHERE t.account_id = 1 ORDER BY t.value_date DESC,t.id DESC

窗口功能如何工作?

(別忘了預訂我們SQL Masterclass來了解窗口函數 ,以及更多!)

盡管有時語法有些令人恐懼,但窗口函數確實非常易于理解。 Windows是您的FROM / WHERE / GROUP BY / HAVING子句中產生的數據的“視圖”。 它們使您可以訪問相對于當前行的所有其他行,同時在SELECT子句中(或很少在ORDER BY子句中)進行計算。 上面的聲明實際上是這樣做的:

| ID | VALUE_DATE | AMOUNT | BALANCE | |------|------------|---------|----------| | 9997 | 2014-03-18 | -(99.17)|+19985.81 | | 9981 | 2014-03-16 | -(71.44)| 19886.64 | | 9979 | 2014-03-16 |-(-94.60)| 19815.20 | | 9977 | 2014-03-16 | -6.96 |=19909.80 | | 9971 | 2014-03-15 | -65.95 | 19916.76 |

也就是說,對于任何給定的余額,從當前余額中減去SUM() “ OVER() ”與當前行(同一銀行帳戶)在同一分區中的所有行的窗口,并且這些行嚴格位于“當前行。

或者,詳細而言:

  • PARTITION BY指定“ OVER() ”,該字符將窗口范圍排成一行
  • ORDER BY指定窗口的排序方式
  • ROWS指定應考慮的有序行索引

我們可以使用Java集合嗎?

我們可以! 如果您使用的是jOOλ :我們設計了一個完全免費的開源Apache 2.0許可庫,因為我們認為JDK 8 Stream和Collector API只是不這樣做。

設計Java 8時,很多精力都放在了支持并行流上。 很好,但是當然不是唯一可以應用函數式編程的有用領域。 我們創建了jOOλ來填補這一空白-無需實現所有新的替代集合API,例如Javaslang或功能性Java have。

jOOλ已經提供:

  • 元組類型
  • 對于有序的,僅順序的流更有用的東西
  • 通過最近發布的jOOλ0.9.9,我們添加了兩個主要新功能:

  • 大量新收藏家
  • 視窗功能
  • JDK中許多缺少的收集器

    JDK附帶了幾個收集器,但是它們看起來確實笨拙且冗長,并且沒有人真正喜歡編寫像此Stack Overflow問題 (以及許多其他問題)中所介紹的收集器那樣的收集器。

    但是鏈接問題中公開的用例是非常有效的。 您要匯總人員列表中的幾件事:

    public class Person {private String firstName;private String lastName;private int age;private double height;private double weight;// getters / setters

    假設您有以下列表:

    List<Person> personsList = new ArrayList<Person>();personsList.add(new Person("John", "Doe", 25, 1.80, 80)); personsList.add(new Person("Jane", "Doe", 30, 1.69, 60)); personsList.add(new Person("John", "Smith", 35, 174, 70));

    現在,您希望獲得以下聚合:

    • 人數
    • 最高年齡
    • 最小高度
    • 平均重量

    對于任何習慣編寫SQL的人來說,這都是一個荒謬的問題:

    SELECT count(*), max(age), min(height), avg(weight) FROM person

    做完了 Java有多難? 事實證明,許多原始代碼需要使用香草JDK 8 API編寫。 考慮給出的復雜答案

    • 由塔吉爾·瓦列夫(Tagir Valeev)
    • 通過TriCore

    使用jOOλ0.9.9時,再次解決此問題變得非常可笑, 并且讀取的內容幾乎類似于SQL :

    Tuple result = Seq.seq(personsList).collect(count(),max(Person::getAge),min(Person::getHeight),avg(Person::getWeight));System.out.println(result);

    結果如下:

    (3, Optional[35], Optional[1.69], Optional[70.0])

    請注意,這不是針對SQL數據庫運行查詢(這就是jOOQ的目的)。 我們正在針對內存中的Java集合運行此“查詢”。

    現在窗口功能如何?

    是的,本文的標題并沒有涉及瑣碎的聚合工作。 它承諾了很棒的窗口功能。

    但是,窗口函數不過是數據流子集上的聚合(或排名)而已。 您想要維護原始記錄,而不是將所有流(或表)聚合到單個記錄中,而是直接在每個單獨的記錄上提供聚合。

    窗口函數的一個很好的入門示例是本文提供的示例,它解釋了ROW_NUMBER(),RANK()和DENSE_RANK()之間的區別 。 考慮以下PostgreSQL查詢:

    SELECTv, ROW_NUMBER() OVER(w),RANK() OVER(w),DENSE_RANK() OVER(w) FROM (VALUES('a'),('a'),('a'),('b'),('c'),('c'),('d'),('e') ) t(v) WINDOW w AS (ORDER BY v);

    它產生:

    | V | ROW_NUMBER | RANK | DENSE_RANK | |---|------------|------|------------| | a | 1 | 1 | 1 | | a | 2 | 1 | 1 | | a | 3 | 1 | 1 | | b | 4 | 4 | 2 | | c | 5 | 5 | 3 | | c | 6 | 5 | 3 | | d | 7 | 7 | 4 | | e | 8 | 8 | 5 |

    在Java 8中,可以使用jOOλ0.9.9進行相同的操作

    System.out.println(Seq.of("a", "a", "a", "b", "c", "c", "d", "e").window(naturalOrder()).map(w -> tuple(w.value(),w.rowNumber(),w.rank(),w.denseRank())).format() );

    屈服…

    +----+----+----+----+ | v0 | v1 | v2 | v3 | +----+----+----+----+ | a | 0 | 0 | 0 | | a | 1 | 0 | 0 | | a | 2 | 0 | 0 | | b | 3 | 3 | 1 | | c | 4 | 4 | 2 | | c | 5 | 4 | 2 | | d | 6 | 6 | 3 | | e | 7 | 7 | 4 | +----+----+----+----+

    同樣,請注意,我們沒有對數據庫運行任何查詢。 一切都在內存中完成。

    注意兩件事:

    • jOOλ的窗口函數返回0(基于Java API的期望值),而不是SQL(全為1)。
    • 在Java中,無法使用命名列構造臨時記錄。 不幸的是,我確實希望將來的Java將為此類語言功能提供支持。

    讓我們回顧一下代碼中到底發生了什么:

    System.out.println(// This is just enumerating our valuesSeq.of("a", "a", "a", "b", "c", "c", "d", "e")// Here, we specify a single window to be// ordered by the value T in the stream, in// natural order.window(naturalOrder())// The above window clause produces a Window<T>// object (the w here), which exposes....map(w -> tuple(// ... the current value itself, of type String...w.value(),// ... or various rankings or aggregations on// the above window.w.rowNumber(),w.rank(),w.denseRank()))// Just some nice formatting to produce the table.format() );

    而已! 很簡單,不是嗎?

    我們可以做的更多! 看一下這個:

    System.out.println(Seq.of("a", "a", "a", "b", "c", "c", "d", "e").window(naturalOrder()).map(w -> tuple(w.value(), // v0 w.count(), // v1w.median(), // v2w.lead(), // v3w.lag(), // v4w.toString() // v5)).format() );

    以上產量是多少?

    +----+----+----+---------+---------+----------+ | v0 | v1 | v2 | v3 | v4 | v5 | +----+----+----+---------+---------+----------+ | a | 1 | a | a | {empty} | a | | a | 2 | a | a | a | aa | | a | 3 | a | b | a | aaa | | b | 4 | a | c | a | aaab | | c | 5 | a | c | b | aaabc | | c | 6 | a | d | c | aaabcc | | d | 7 | b | e | c | aaabccd | | e | 8 | b | {empty} | d | aaabccde | +----+----+----+---------+---------+----------+

    現在,您的分析心臟應該跳了起來。

    等一會兒。 我們也可以像在SQL中那樣做框架嗎? 我們可以。 就像在SQL中一樣,當我們省略窗口定義上的frame子句(但我們確實指定了ORDER BY子句)時,默認情況下將應用以下內容:

    RANGE BETWEEN UNBOUNDED PRECEDINGAND CURRENT ROW

    我們在前面的示例中已經做到了。 可以在第v5列中看到,在該列中我們從第一個值到當前值聚合字符串。 因此,讓我們指定框架:

    System.out.println(Seq.of("a", "a", "a", "b", "c", "c", "d", "e").window(naturalOrder(), -1, 1) // frame here.map(w -> tuple(w.value(), // v0w.count(), // v1w.median(), // v2w.lead(), // v3w.lag(), // v4w.toString() // v5)).format() );

    結果很簡單:

    +----+----+----+---------+---------+-----+ | v0 | v1 | v2 | v3 | v4 | v5 | +----+----+----+---------+---------+-----+ | a | 2 | a | a | {empty} | aa | | a | 3 | a | a | a | aaa | | a | 3 | a | b | a | aab | | b | 3 | b | c | a | abc | | c | 3 | c | c | b | bcc | | c | 3 | c | d | c | ccd | | d | 3 | d | e | c | cde | | e | 2 | d | {empty} | d | de | +----+----+----+---------+---------+-----+

    如預期的那樣, lead()和lag()不受影響,這與count() , median()和toString()相反

    現在,讓我們回顧一下運行總計。

    通常,您不會根據流本身的標量值來計算窗口函數,因為該值通常不是標量值,而是元組(或Java語言中的POJO)。 取而代之的是,您從元組(或POJO)中提取值并對其進行匯總。 因此,再次,在計算BALANCE ,我們需要首先提取AMOUNT 。

    | ID | VALUE_DATE | AMOUNT | BALANCE | |------|------------|---------|----------| | 9997 | 2014-03-18 | -(99.17)|+19985.81 | | 9981 | 2014-03-16 | -(71.44)| 19886.64 | | 9979 | 2014-03-16 |-(-94.60)| 19815.20 | | 9977 | 2014-03-16 | -6.96 |=19909.80 | | 9971 | 2014-03-15 | -65.95 | 19916.76 |

    這是使用Java 8和jOOλ0.9.9編寫運行總計的方法

    BigDecimal currentBalance = new BigDecimal("19985.81");Seq.of(tuple(9997, "2014-03-18", new BigDecimal("99.17")),tuple(9981, "2014-03-16", new BigDecimal("71.44")),tuple(9979, "2014-03-16", new BigDecimal("-94.60")),tuple(9977, "2014-03-16", new BigDecimal("-6.96")),tuple(9971, "2014-03-15", new BigDecimal("-65.95"))) .window(Comparator.comparing((Tuple3<Integer, String, BigDecimal> t) -> t.v1, reverseOrder()).thenComparing(t -> t.v2), Long.MIN_VALUE, -1) .map(w -> w.value().concat(currentBalance.subtract(w.sum(t -> t.v3).orElse(BigDecimal.ZERO)) ));

    屈服

    +------+------------+--------+----------+ | v0 | v1 | v2 | v3 | +------+------------+--------+----------+ | 9997 | 2014-03-18 | 99.17 | 19985.81 | | 9981 | 2014-03-16 | 71.44 | 19886.64 | | 9979 | 2014-03-16 | -94.60 | 19815.20 | | 9977 | 2014-03-16 | -6.96 | 19909.80 | | 9971 | 2014-03-15 | -65.95 | 19916.76 | +------+------------+--------+----------+

    這里有幾件事發生了變化:

    • 比較器現在考慮兩個比較。 不幸的是JEP-101并沒有完全實現 ,這就是為什么我們需要在此處幫助類型編譯器的原因。
    • Window.value()現在是一個元組,而不是單個值。 因此,我們需要從中提取有趣的列AMOUNT (通過t -> t.v3 )。 另一方面,我們可以簡單地將附加值concat()給元組

    但是已經足夠了。 除了比較器的詳細信息(我們一定會在將來的jOOλ版本中解決)之外,編寫窗口函數也是小菜一碟。

    我們還能做什么?

    本文不是對新API可以做的所有事情的完整描述。 我們將很快寫一個后續博客文章,并提供其他示例。 例如:

    • 未描述partition by子句,但也可用
    • 您可以指定比此處公開的單個窗口更多的窗口,每個窗口都具有單獨的PARTITION BY , ORDER BY和框架規范

    另外,當前的實現還很規范,即它尚未(尚未)緩存聚合:

    • 對于無序/無框窗口(所有分區的值相同)
    • 嚴格升序的窗口(聚合可以基于先前的值,例如SUM()或toString()關聯收集器)

    就我們而言就是這樣。 下載jOOλ,試用它,并享受一個事實,那就是所有Java 8開發人員現在都可以使用最強大SQL功能!

    • https://github.com/jOOQ/jOOL

    翻譯自: https://www.javacodegeeks.com/2016/01/2016-will-year-remembered-java-finally-window-functions.html

    java關閉窗口函數

    總結

    以上是生活随笔為你收集整理的java关闭窗口函数_2016年将是Java终于拥有窗口函数的那一年!的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。