<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>OpenText Analytics Database 26.2.x – Window framing</title>
    <link>/en/data-analysis/sql-analytics/window-framing/</link>
    <description>Recent content in Window framing on OpenText Analytics Database 26.2.x</description>
    <generator>Hugo -- gohugo.io</generator>
    
	  <atom:link href="/en/data-analysis/sql-analytics/window-framing/index.xml" rel="self" type="application/rss+xml" />
    
    
      
        
      
    
    
    <item>
      <title>Data-Analysis: Windows with a physical offset (ROWS)</title>
      <link>/en/data-analysis/sql-analytics/window-framing/windows-with-physical-offset-rows/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/data-analysis/sql-analytics/window-framing/windows-with-physical-offset-rows/</guid>
      <description>
        
        
        &lt;p&gt;The keyword &lt;code&gt;ROWS&lt;/code&gt; in a window frame clause specifies window dimensions as the number of rows relative to the current row. The value can be &lt;code&gt;INTEGER&lt;/code&gt; data type only.

&lt;div class=&#34;alert admonition note&#34; role=&#34;alert&#34;&gt;
&lt;h4 class=&#34;admonition-head&#34;&gt;Note&lt;/h4&gt;

The value returned by an analytic function with a physical offset is liable to produce nondeterministic results unless the ordering expression results in a unique ordering. To achieve unique ordering, the &lt;a href=&#34;../../../../en/sql-reference/language-elements/window-clauses/window-order-clause/&#34;&gt;window order clause&lt;/a&gt; might need to specify multiple columns.

&lt;/div&gt;&lt;/p&gt;
&lt;h2 id=&#34;examples&#34;&gt;Examples&lt;/h2&gt;
&lt;p&gt;The examples on this page use the &lt;code&gt;emp&lt;/code&gt; table schema:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;CREATE TABLE emp(deptno INT, sal INT, empno INT);
INSERT INTO emp VALUES(10,101,1);
INSERT INTO emp VALUES(10,104,4);
INSERT INTO emp VALUES(20,100,11);
INSERT INTO emp VALUES(20,109,7);
INSERT INTO emp VALUES(20,109,6);
INSERT INTO emp VALUES(20,109,8);
INSERT INTO emp VALUES(20,110,10);
INSERT INTO emp VALUES(20,110,9);
INSERT INTO emp VALUES(30,102,2);
INSERT INTO emp VALUES(30,103,3);
INSERT INTO emp VALUES(30,105,5);
COMMIT;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The following query invokes &lt;code&gt;COUNT&lt;/code&gt; to count the current row and the rows preceding it, up to two rows:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;SELECT deptno, sal, empno,  COUNT(*) OVER
         (&lt;span class=&#34;code-input&#34;&gt;&lt;/span&gt;PARTITION BY deptno ORDER BY&lt;span class=&#34;code-input&#34;&gt; &lt;/span&gt;sal &lt;span class=&#34;code-input&#34;&gt;&lt;/span&gt;&lt;span class=&#34;code-input&#34;&gt;ROWS &lt;/span&gt;&lt;span class=&#34;code-input&#34;&gt;BETWEEN 2 PRECEDING AND CURRENT ROW&lt;/span&gt;)
        AS count FROM emp;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The &lt;code&gt;OVER&lt;/code&gt; clause contains three components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Window partition clause &lt;code&gt;PARTITION BY deptno&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Order by clause &lt;code&gt;ORDER BY sal&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Window frame clause &lt;code&gt;ROWS BETWEEN 2 PRECEDING AND CURRENT ROW&lt;/code&gt; . This clause defines window dimensions as extending from the current row through the two rows that precede it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The query returns results that are divided into three partitions, indicated below as red lines. Within the second partition (&lt;code&gt;deptno=20&lt;/code&gt;), &lt;code&gt;COUNT&lt;/code&gt; processes the window frame clause as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Creates the first window (green box). This window comprises a single row, as the current row (blue box) is also the the partition&#39;s first row. Thus, the value in the &lt;code&gt;count&lt;/code&gt; column shows the number of rows in the current window, which is 1:&lt;br /&gt;&lt;img src=&#34;../../../../images/framing-windows-with-rows8.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After &lt;code&gt;COUNT&lt;/code&gt; processes the partition&#39;s first row, it resets the current row to the partition&#39;s second row. The window now spans the current row and the row above it, so &lt;code&gt;COUNT&lt;/code&gt; returns a value of 2:&lt;br /&gt;&lt;img src=&#34;../../../../images/framing-windows-with-rows9.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;After &lt;code&gt;COUNT&lt;/code&gt; processes the partition&#39;s second row, it resets the current row to the partition&#39;s third row. The window now spans the current row and the two rows above it, so &lt;code&gt;COUNT&lt;/code&gt; returns a value of 3:&lt;br /&gt;&lt;img src=&#34;../../../../images/framing-windows-with-rows10.png&#34; alt=&#34;&#34;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Thereafter, &lt;code&gt;COUNT&lt;/code&gt; continues to process the remaining partition rows and moves the window accordingly, but the window dimensions (&lt;code&gt;ROWS BETWEEN 2 PRECEDING AND CURRENT ROW&lt;/code&gt;) remain unchanged as three rows. Accordingly, the value in the &lt;code&gt;count&lt;/code&gt; column also remains unchanged (3):&lt;br /&gt;&lt;img src=&#34;../../../../images/framing-windows-with-rows11.png&#34; alt=&#34;&#34;&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&#34;../../../../images/framing-windows-with-rows12.png&#34; alt=&#34;&#34;&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src=&#34;../../../../images/framing-windows-with-rows13.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

      </description>
    </item>
    
    <item>
      <title>Data-Analysis: Windows with a logical offset (RANGE)</title>
      <link>/en/data-analysis/sql-analytics/window-framing/windows-with-logical-offset-range/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/data-analysis/sql-analytics/window-framing/windows-with-logical-offset-range/</guid>
      <description>
        
        
        &lt;p&gt;The &lt;code&gt;RANGE&lt;/code&gt; keyword defines an analytic window frame as a logical offset from the current row.

&lt;div class=&#34;alert admonition note&#34; role=&#34;alert&#34;&gt;
&lt;h4 class=&#34;admonition-head&#34;&gt;Note&lt;/h4&gt;

The value returned by an analytic function with a logical offset is always deterministic.

&lt;/div&gt;&lt;/p&gt;
&lt;p&gt;For each row, an analytic function uses the &lt;a href=&#34;../../../../en/sql-reference/language-elements/window-clauses/window-order-clause/&#34;&gt;window order clause&lt;/a&gt; (&lt;code&gt;ORDER_BY&lt;/code&gt;) column or expression to calculate window frame dimensions as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Within the current partition, evaluates the &lt;code&gt;ORDER_BY&lt;/code&gt; value of the current row against the &lt;code&gt;ORDER_BY&lt;/code&gt; values of contiguous rows.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Determines which of these rows satisfy the specified range requirements relative to the current row.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Creates a window frame that includes only those rows.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Executes on the current window.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;example&#34;&gt;Example&lt;/h2&gt;
&lt;p&gt;This example uses the table &lt;code&gt;property_sales&lt;/code&gt;, which contains data about neighborhood home sales:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT property_key, neighborhood, sell_price FROM property_sales ORDER BY neighborhood, sell_price;
 property_key | neighborhood  | sell_price
--------------+---------------+------------
        10918 | Jamaica Plain |     353000
        10921 | Jamaica Plain |     450000
        10927 | Jamaica Plain |     450000
        10922 | Jamaica Plain |     474000
        10919 | Jamaica Plain |     515000
        10917 | Jamaica Plain |     675000
        10924 | Jamaica Plain |     675000
        10920 | Jamaica Plain |     705000
        10923 | Jamaica Plain |     710000
        10926 | Jamaica Plain |     875000
        10925 | Jamaica Plain |     900000
        10930 | Roslindale    |     300000
        10928 | Roslindale    |     422000
        10932 | Roslindale    |     450000
        10929 | Roslindale    |     485000
        10931 | Roslindale    |     519000
        10938 | West Roxbury  |     479000
        10933 | West Roxbury  |     550000
        10937 | West Roxbury  |     550000
        10934 | West Roxbury  |     574000
        10935 | West Roxbury  |     598000
        10936 | West Roxbury  |     615000
        10939 | West Roxbury  |     720000
(23 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;The analytic function &lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/avg-analytic/&#34;&gt;AVG&lt;/a&gt; can obtain the average of proximate selling prices within each neighborhood. The following query calculates for each home the average sale for all other neighborhood homes whose selling price was $50k higher or lower:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT property_key, neighborhood, sell_price, AVG(sell_price) OVER(
     PARTITION BY neighborhood ORDER BY sell_price
     RANGE BETWEEN 50000 PRECEDING and 50000 FOLLOWING)::int AS comp_sales
     FROM property_sales ORDER BY neighborhood;
 property_key | neighborhood  | sell_price | comp_sales
--------------+---------------+------------+------------
        10918 | Jamaica Plain |     353000 |     353000
        10927 | Jamaica Plain |     450000 |     458000
        10921 | Jamaica Plain |     450000 |     458000
        10922 | Jamaica Plain |     474000 |     472250
        10919 | Jamaica Plain |     515000 |     494500
        10917 | Jamaica Plain |     675000 |     691250
        10924 | Jamaica Plain |     675000 |     691250
        10920 | Jamaica Plain |     705000 |     691250
        10923 | Jamaica Plain |     710000 |     691250
        10926 | Jamaica Plain |     875000 |     887500
        10925 | Jamaica Plain |     900000 |     887500
        10930 | Roslindale    |     300000 |     300000
        10928 | Roslindale    |     422000 |     436000
        10932 | Roslindale    |     450000 |     452333
        10929 | Roslindale    |     485000 |     484667
        10931 | Roslindale    |     519000 |     502000
        10938 | West Roxbury  |     479000 |     479000
        10933 | West Roxbury  |     550000 |     568000
        10937 | West Roxbury  |     550000 |     568000
        10934 | West Roxbury  |     574000 |     577400
        10935 | West Roxbury  |     598000 |     577400
        10936 | West Roxbury  |     615000 |     595667
        10939 | West Roxbury  |     720000 |     720000
(23 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;AVG processes this query as follows:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;AVG&lt;/code&gt; evaluates row 1 of the first partition (Jamaica Plain), but finds no sales within $50k of this row&#39;s &lt;code&gt;sell_price&lt;/code&gt;, ($353k). &lt;code&gt;AVG&lt;/code&gt; creates a window that includes this row only, and returns an average of 353k for row 1:&lt;br /&gt;&lt;br /&gt;&lt;img src=&#34;../../../../images/sql-analytics/window-frame-logical1.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;AVG&lt;/code&gt; evaluates row 2 and finds three &lt;code&gt;sell_price&lt;/code&gt; values within $50k of the current row. &lt;code&gt;AVG&lt;/code&gt; creates a window that includes these three rows, and returns an average of 458k for row 2:&lt;br /&gt;&lt;img src=&#34;../../../../images/sql-analytics/window-frame-logical1a.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;AVG&lt;/code&gt; evaluates row 3 and finds the same three &lt;code&gt;sell_price&lt;/code&gt; values within $50k of the current row. &lt;code&gt;AVG&lt;/code&gt; creates a window identical to the one before, and returns the same average of 458k for row 3:&lt;br /&gt;&lt;img src=&#34;../../../../images/sql-analytics/window-frame-logical1b.png&#34; alt=&#34;&#34;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;AVG&lt;/code&gt; evaluates row 4 and finds four &lt;code&gt;sell_price&lt;/code&gt; values within $50k of the current row. &lt;code&gt;AVG&lt;/code&gt; expands its window to include rows 2 through 5, and returns an average of $472.25k for row 4:&lt;br /&gt;&lt;img src=&#34;../../../../images/sql-analytics/window-frame-logical2.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In similar fashion, &lt;code&gt;AVG&lt;/code&gt; evaluates the remaining rows in this partition. When the function evaluates the first row of the second partition (Roslindale), it resets the window as follows:&lt;br /&gt;&lt;img src=&#34;../../../../images/sql-analytics/window-frame-logical3.png&#34; alt=&#34;&#34;&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;restrictions&#34;&gt;Restrictions&lt;/h2&gt;
&lt;p&gt;If &lt;code&gt;RANGE&lt;/code&gt; specifies a constant value, that value&#39;s data type and the window&#39;s &lt;code&gt;ORDER BY&lt;/code&gt; data type must be the same. The following exceptions apply:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;RANGE&lt;/code&gt; can specify &lt;code&gt;INTERVAL Year to Month&lt;/code&gt; if the window order clause data type is one of following: &lt;code&gt;TIMESTAMP&lt;/code&gt;, &lt;code&gt;TIMESTAMP WITH TIMEZONE&lt;/code&gt;, or &lt;code&gt;DATE&lt;/code&gt;. &lt;code&gt;TIME&lt;/code&gt; and &lt;code&gt;TIME WITH TIMEZONE&lt;/code&gt; are not supported.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;RANGE&lt;/code&gt; can specify &lt;code&gt;INTERVAL Day to Second&lt;/code&gt; if the window order clause data is one of following: &lt;code&gt;TIMESTAMP&lt;/code&gt;, &lt;code&gt;TIMESTAMP WITH TIMEZONE&lt;/code&gt;, &lt;code&gt;DATE&lt;/code&gt;, &lt;code&gt;TIME&lt;/code&gt;, or &lt;code&gt;TIME WITH TIMEZONE&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The window order clause must specify one of the following data types: &lt;code&gt;NUMERIC&lt;/code&gt;, &lt;code&gt;DATE/TIME&lt;/code&gt;, &lt;code&gt;FLOAT&lt;/code&gt; or &lt;code&gt;INTEGER&lt;/code&gt;. This requirement is ignored if the window specifies one of following frames:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

      </description>
    </item>
    
    <item>
      <title>Data-Analysis: Reporting aggregates</title>
      <link>/en/data-analysis/sql-analytics/window-framing/reporting-aggregates/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/en/data-analysis/sql-analytics/window-framing/reporting-aggregates/</guid>
      <description>
        
        
        &lt;p&gt;Some of the analytic functions that take the window-frame-clause are the reporting aggregates. These functions let you compare a partition&#39;s aggregate values with detail rows, taking the place of correlated subqueries or joins.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/avg-analytic/&#34;&gt;AVG()&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/count-analytic/&#34;&gt;COUNT()&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/max-analytic/&#34;&gt;MAX()&lt;/a&gt; and &lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/min-analytic/&#34;&gt;MIN()&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/sum-analytic/&#34;&gt;SUM()&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/stddev-analytic/&#34;&gt;STDDEV()&lt;/a&gt;, &lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/stddev-analytic/&#34;&gt;STDDEV_POP()&lt;/a&gt;, and &lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/stddev-analytic/&#34;&gt;STDDEV_SAMP()&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/variance-analytic/&#34;&gt;VARIANCE()&lt;/a&gt;, &lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/var-pop-analytic/&#34;&gt;VAR_POP()&lt;/a&gt;, and &lt;a href=&#34;../../../../en/sql-reference/functions/analytic-functions/var-samp-analytic/&#34;&gt;VAR_SAMP()&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you use a window aggregate with an empty OVER() clause, the analytic function is used as a reporting function, where the entire input is treated as a single partition.&lt;/p&gt;
&lt;h2 id=&#34;about-standard-deviation-and-variance-functions&#34;&gt;About standard deviation and variance functions&lt;/h2&gt;
&lt;p&gt;With standard deviation functions, a low standard deviation indicates that the data points tend to be very close to the mean, whereas high standard deviation indicates that the data points are spread out over a large range of values.&lt;/p&gt;
&lt;p&gt;Standard deviation is often graphed and a distributed standard deviation creates the classic bell curve.&lt;/p&gt;
&lt;p&gt;Variance functions measure how far a set of numbers is spread out.&lt;/p&gt;
&lt;h2 id=&#34;examples&#34;&gt;Examples&lt;/h2&gt;
&lt;p&gt;Think of the window for reporting aggregates as a window defined as UNBOUNDED PRECEDING and UNBOUNDED FOLLOWING. The omission of a window-order-clause makes all rows in the partition also the window (reporting aggregates).&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT deptno, sal, empno, COUNT(sal)
  OVER (PARTITION BY deptno) AS COUNT FROM emp;
 deptno | sal | empno | count
--------+-----+-------+-------
     10 | 101 |     1 |     2
     10 | 104 |     4 |     2
&lt;span class=&#34;code-input&#34;&gt;------------------------------&lt;/span&gt;
     20 | 110 |    10 |     6
     20 | 110 |     9 |     6
     20 | 109 |     7 |     6
     20 | 109 |     6 |     6
     20 | 109 |     8 |     6
     20 | 100 |    11 |     6
&lt;span class=&#34;code-input&#34;&gt;------------------------------&lt;/span&gt;
     30 | 105 |     5 |     3
     30 | 103 |     3 |     3
     30 | 102 |     2 |     3
(11 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If the OVER() clause in the above query contained a &lt;code&gt;window-order-clause&lt;/code&gt; (for example, ORDER BY sal), it would become a moving window (window aggregate) query with a default window of RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT deptno, sal, empno, COUNT(sal)  OVER (PARTITION BY deptno ORDER BY sal) AS COUNT FROM emp;
 deptno | sal | empno | count
--------+-----+-------+-------
     10 | 101 |     1 |     1
     10 | 104 |     4 |     2
&lt;span class=&#34;code-input&#34;&gt;------------------------------&lt;/span&gt;
     20 | 100 |    11 |     1
     20 | 109 |     7 |     4
     20 | 109 |     6 |     4
     20 | 109 |     8 |     4
     20 | 110 |    10 |     6
     20 | 110 |     9 |     6
&lt;span class=&#34;code-input&#34;&gt;------------------------------&lt;/span&gt;
     30 | 102 |     2 |     1
     30 | 103 |     3 |     2
     30 | 105 |     5 |     3
(11 rows)
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;what-about-last_value&#34;&gt;What about LAST_VALUE?&lt;/h2&gt;
&lt;p&gt;You might wonder why you couldn&#39;t just use the LAST_VALUE() analytic function.&lt;/p&gt;
&lt;p&gt;For example, for each employee, get the highest salary in the department:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT deptno, sal, empno,LAST_VALUE(empno) OVER (PARTITION BY deptno ORDER BY sal) AS lv FROM emp;
![](/images/reporting-aggregates2.png)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Due to default window semantics, LAST_VALUE does not always return the last value of a partition. If you omit the window-frame-clause from the analytic clause, LAST_VALUE operates on this default window. Results, therefore, can seem non-intuitive because the function does not return the bottom of the current partition. It returns the bottom of the window, which continues to change along with the current input row being processed.&lt;/p&gt;
&lt;p&gt;Remember the default window:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;OVER (PARTITION BY deptno ORDER BY sal)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;is the same as:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;OVER(PARTITION BY deptno ORDER BY salROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;
&lt;table class=&#34;table table-bordered&#34; &gt;



&lt;tr&gt; 

&lt;td &gt;
&lt;img src=&#34;../../../../images/reporting-aggregates3.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt; 

&lt;td &gt;
&lt;img src=&#34;../../../../images/reporting-aggregates4.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;


&lt;table class=&#34;table table-bordered&#34; &gt;



&lt;tr&gt; 

&lt;td &gt;
&lt;img src=&#34;../../../../images/reporting-aggregates5.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt; 

&lt;td &gt;
&lt;img src=&#34;../../../../images/reporting-aggregates6.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;


&lt;table class=&#34;table table-bordered&#34; &gt;



&lt;tr&gt; 

&lt;td &gt;
&lt;img src=&#34;../../../../images/reporting-aggregates7.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt; 

&lt;td &gt;
&lt;img src=&#34;../../../../images/reporting-aggregates8.png&#34; alt=&#34;&#34;&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/p&gt;
&lt;p&gt;If you want to return the last value of a partition, use UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT deptno, sal, empno, LAST_VALUE(empno)
OVER (PARTITION BY deptno ORDER BY sal
&lt;span class=&#34;code-input&#34;&gt;ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING&lt;/span&gt;) AS lv
FROM emp;
![](/images/reporting-aggregates9.png)
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;OpenText recommends that you use LAST_VALUE with the window-order-clause to produce deterministic results.&lt;/p&gt;
&lt;p&gt;In the following example, empno 6, 7, and 8 have the same salary, so they are in adjacent rows. empno 8 appears first in this case but the order is not guaranteed.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../../../images/reporting-aggregates10.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Notice in the output above, the last value is 7, which is the last row from the partition deptno = 20. If the rows have a different order, then the function returns a different value:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;../../../../images/reporting-aggregates11.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now the last value is 6, which is the last row from the partition deptno = 20. The solution is to add a unique key to the sort order. Even if the order of the query changes, the result will always be the same, and so deterministic.&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;=&amp;gt; SELECT deptno, sal, empno, LAST_VALUE(empno)
OVER (PARTITION BY deptno ORDER BY sal, &lt;span class=&#34;code-input&#34;&gt;empno &lt;/span&gt;
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) as lv
FROM emp;
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;img src=&#34;../../../../images/reporting-aggregates12.png&#34; alt=&#34;&#34;&gt;&lt;/p&gt;
&lt;p&gt;Notice how the rows are now ordered by &lt;code&gt;empno&lt;/code&gt;, the last value stays at 8, and it does not matter the order of the query.&lt;/p&gt;

      </description>
    </item>
    
  </channel>
</rss>
