Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Work on the window function documentation, including importing the new syntax diagrams. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
6d60e5d0211950dddab8ea8f6ae5c799 |
User & Date: | drh 2018-07-06 20:43:09.462 |
Context
2018-07-07
| ||
17:36 | Minor changes to the windows function documentation. (check-in: ff1e1e885a user: drh tags: trunk) | |
2018-07-06
| ||
20:43 | Work on the window function documentation, including importing the new syntax diagrams. (check-in: 6d60e5d021 user: drh tags: trunk) | |
18:30 | Update the syntax diagrams to include the new window function syntax. (check-in: f7a6a2f7c2 user: drh tags: trunk) | |
Changes
Changes to pages/windowfunctions.in.
︙ | ︙ | |||
11 12 13 14 15 16 17 | <h1>Introduction to Window Functions</h1> <p>A window function is a special type of SQL function for which the results depend on the contents of a "window" of one or more contiguous rows returned by the SELECT statement containing the window function. A window function may only be used in the select-list or ORDER BY clause of a SELECT or sub-select | | > | | | | < | | | | | | | < < < > | | | > | | | > | | | | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | <h1>Introduction to Window Functions</h1> <p>A window function is a special type of SQL function for which the results depend on the contents of a "window" of one or more contiguous rows returned by the SELECT statement containing the window function. A window function may only be used in the select-list or ORDER BY clause of a SELECT or sub-select construction. The syntax for a window function is similar to that for a regular scalar SQL function except that it is followed by an OVER clause. The full syntax is as follows: <tcl> RecursiveBubbleDiagram window-function-invocation </tcl> <p>Window function are distingished from ordinary SQL functions by the presence of an OVER clause. If a function invocation has an OVER clause then it is a window function, and if lacks a OVER clause it is an ordinary function. Window functions might also have a FILTER clause in between the function and the OVER clause. Unlike ordinary functions, window functions cannot use the DISTINCT keyword. <p>The following simple table is used to demonstrate how window functions work: <codeblock> CREATE TABLE t0(x INTEGER PRIMARY KEY, y TEXT); INSERT INTO t0 VALUES (1, 'aaa'), (2, 'ccc'), (3, 'bbb'); </codeblock> <p>An example of using window functions: <codeblock> <i>-- The following SELECT statement returns:</i> <i>-- </i> <i>-- x | y | row_number</i> ----------------------- <i>-- 1 | aaa | 1 </i> <i>-- 2 | ccc | 3 </i> <i>-- 3 | bbb | 2 </i> <i>-- </i> SELECT x, y, row_number() OVER (ORDER BY y) AS row_number FROM t0 ORDER BY x; </codeblock> <p>The example uses the built-in window function row_number(). The row_number() window function assigns a monotonically increasing integer to each row in order of the the "ORDER BY" clause within the <yynonterm>window-defn</yynonterm> (in this case "ORDER BY y"). Note that this does not affect the order in which results are returned from the overall query. The order of the final output is is still governed by the ORDER BY clause attached to the SELECT statement (in this case "ORDER BY x"). <p>Named <yynonterm>window-defn</yynonterm> clauses may also be added to a SELECT statement using a WINDOW clause and then refered to by name within window function invocations. For example, the following SELECT statement contains two named <yynonterm>window-defs</yynonterm> clauses, "win1" and "win2": <codeblock> SELECT x, y, row_number() OVER <b>win1</b>, rank() OVER <b>win2</b> FROM t0 WINDOW <b>win1</b> AS (ORDER BY y RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), <b>win2</b> AS (PARTITION BY y ORDER BY x) ORDER BY x; </codeblock> <p>The WINDOW clause, when one is present, comes after any HAVING clause and before any ORDER BY. |
︙ | ︙ | |||
117 118 119 120 121 122 123 | ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) AS group_concat FROM t1; </codeblock> <p> In the example above, the window frame consists of all rows between the previous row ("1 PRECEDING") and the following row ("1 FOLLOWING"), inclusive, where rows are sorted according to the ORDER BY clause in the | > | > > | > | | > > > > | | > > > | > > > > > > > > > > | < | | | | | < | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | ORDER BY a ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING ) AS group_concat FROM t1; </codeblock> <p> In the example above, the window frame consists of all rows between the previous row ("1 PRECEDING") and the following row ("1 FOLLOWING"), inclusive, where rows are sorted according to the ORDER BY clause in the <yynonterm>window-defn</yynonterm> (in this case "ORDER BY a"). For example, the frame for the row with (a=3) consists of rows (2, 'B', 'two'), (3, 'C', 'three') and (4, 'D', 'one'). The result of group_concat(b, '.') for that row is therefore 'B.C.D'. <p> The default <yynonterm>frame-spec</yynonterm> is: <codeblock> RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW </codeblock> <p> This means that, after sorting the rows returned by the SELECT according to the ORDER BY clause in the <yynonterm>window-definition</yynonterm>, the window frame consists of all rows between the first row and the last row with the same values as the current row for all ORDER BY expressions. This implies that rows that have the same values for all ORDER BY expressions will also have the same value for the result of the window function (as the window frame is the same). For example: <codeblock> <i>-- The following SELECT statement returns:</i> <i>-- </i> <i>-- a | b | c | group_concat</i> ----------------------------- <i>-- 1 | A | one | A.D.G </i> <i>-- 2 | B | two | A.D.G.C.F.B.E</i> <i>-- 3 | C | three | A.D.G.C.F </i> <i>-- 4 | D | one | A.D.G </i> <i>-- 5 | E | two | A.D.G.C.F.B.E</i> <i>-- 6 | F | three | A.D.G.C.F </i> <i>-- 7 | G | one | A.D.G </i> <i>-- </i> SELECT a, b, c, group_concat(b, '.') OVER (ORDER BY c) AS group_concat FROM t1 ORDER BY a; </codeblock> <p> All of SQLite's [Aggregate Functions|aggregate functions] may be used as aggregate window functions. It is also possible to [user-defined window functions|create user-defined aggregate window functions]. <h2>Frame Specifications</h2> <tcl> RecursiveBubbleDiagram frame-spec </tcl> <p> The <yynonterm>frame-spec</yynonterm> determines which output rows are read by an aggregate window function. The <yynonterm>frame-spec</yynonterm> consists of three parts: <ul> <li> A frame type - either RANGE or ROWS. <li> A starting frame boundary, and <li> An ending frame boundary. </ul> <p>The default <yynonterm>frame-spec</yynonterm> is: <codeblock> RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW </codeblock> <p> If the frame type is RANGE, then rows with the same values for all ORDER BY expressions are considered "peers". Or, if there are no ORDER BY expressions, all rows are peers. Rows that are peers always have the same window frames. <p> There are five options for frame boundaries: <table striped=1> <tr><th>Frame Boundary <th>Description <tr><td>UNBOUNDED PRECEDING <td> The start of the frame is the first row in the set. <tr><td><expr> PRECEDING <td> <expr> is a constant expression that evaluates to a non-negative integer value. The start or end of the frame is <expr> rows before the current row. "0 PRECEDING" is the same as "CURRENT ROW". This frame boundary type may only be used with ROWS frames. <tr><td>CURRENT ROW <td> The current row. For RANGE frame types, all peers of the current row are also included in the window frame, regardless of whether CURRENT ROW is used as the starting or ending frame boundary. <tr><td><expr> FOLLOWING <td> <expr> is a constant expression that must evaluate to a non-negative integer value. The start or end of the frame is <expr> rows after the current row. "0 FOLLOWING" is the same as "CURRENT ROW". This frame boundary type may only be used with ROWS frames. <tr><td>UNBOUNDED FOLLOWING <td> The end of the frame is the last row in the set. </table> <p> The ending frame boundary must not take a form that appears higher in the above list than the starting frame boundary. <p> In the following example, the window frame for each row consists of all |
︙ | ︙ | |||
218 219 220 221 222 223 224 | ORDER BY c, a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) AS group_concat FROM t1 ORDER BY c, a; </codeblock> <h2>The PARTITION BY Clause</h2> | | | | | | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 | ORDER BY c, a ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) AS group_concat FROM t1 ORDER BY c, a; </codeblock> <h2>The PARTITION BY Clause</h2> <p> A <yynonterm>window-defn</yynonterm> may include a PARTITION BY clause. If so, the rows returned by the SELECT statement are divided into groups - partitions - with the same values for each PARTITION BY expression, and then window-function processing is performed separately for each partition. This is similar to the way the rows are grouped by the GROUP BY clause of an aggregate query. <p> For example: <codeblock> <i>-- The following SELECT statement returns:</i> <i>-- </i> <i>-- c | a | b | group_concat</i> |
︙ | ︙ | |||
248 249 250 251 252 253 254 255 256 257 258 259 260 261 | PARTITION BY c ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) AS group_concat FROM t1 ORDER BY c, a; </codeblock> <h2>The FILTER Clause</h2> <p>If a FILTER clause is provided, then only rows for which the <i>expr</i> is true are included in the window frame. The aggregate window still returns a value for every row, but those for which the FILTER expression evaluates to other than true are not included in the window frame for any row. For example: <codeblock> <i>-- The following SELECT statement returns:</i> | > > > > | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | PARTITION BY c ORDER BY a RANGE BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING ) AS group_concat FROM t1 ORDER BY c, a; </codeblock> <h2>The FILTER Clause</h2> <tcl> RecursiveBubbleDiagram filter </tcl> <p>If a FILTER clause is provided, then only rows for which the <i>expr</i> is true are included in the window frame. The aggregate window still returns a value for every row, but those for which the FILTER expression evaluates to other than true are not included in the window frame for any row. For example: <codeblock> <i>-- The following SELECT statement returns:</i> |
︙ | ︙ | |||
286 287 288 289 290 291 292 | <p> Built-in window functions honor any PARTITION BY clause in the same way as aggregate window functions - each selected row is assigned to a partition and each partition is processed separately. The ways in which any ORDER BY clause affects each built-in window function is described below. Some of the window functions (rank(), dense_rank(), percent_rank() and ntile()) use the concept of "peer groups" (rows within the same partition that have the same values for all ORDER BY expressions). In these cases, it does not matter | | | | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 | <p> Built-in window functions honor any PARTITION BY clause in the same way as aggregate window functions - each selected row is assigned to a partition and each partition is processed separately. The ways in which any ORDER BY clause affects each built-in window function is described below. Some of the window functions (rank(), dense_rank(), percent_rank() and ntile()) use the concept of "peer groups" (rows within the same partition that have the same values for all ORDER BY expressions). In these cases, it does not matter whether the <yynonterm>frame-spec</yynonterm> specifies ROWS or RANGE - for the purposes of built-in window function processing, rows with the same values for all ORDER BY expressions are considered peers regardless of the frame type. <p> Most built-in window functions ignore the <yynonterm>frame-spec</yynonterm>, the exceptions being first_value(), last_value() and nth_value(). It is a syntax error to specify a FILTER clause as part of a built-in window function invocation. <p> SQLite supports the following 11 built-in window functions: <dl> <dt><p><b>row_number()</b> |
︙ | ︙ | |||
446 447 448 449 450 451 452 | ntile(2) OVER win AS ntile_2, ntile(4) OVER win AS ntile_4 FROM t2 WINDOW win AS (ORDER BY a); </codeblock> <p> The next example demonstrates lag(), lead(), first_value(), last_value() | > | > | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 | ntile(2) OVER win AS ntile_2, ntile(4) OVER win AS ntile_4 FROM t2 WINDOW win AS (ORDER BY a); </codeblock> <p> The next example demonstrates lag(), lead(), first_value(), last_value() and nth_value(). The <yynonterm>frame-spec</yynonterm> is ignored by both lag() and lead(), but respected by first_value(), last_value() and nth_value(). <codeblock> <i>-- The following SELECT statement returns:</i> <i>-- </i> <i>-- b | lead | lag | first_value | last_value | nth_value_3</i> ------------------------------------------------------------- <i>-- A | C | NULL | A | A | NULL </i> |
︙ | ︙ |
Changes to rawpages/sqlite.css.
︙ | ︙ | |||
222 223 224 225 226 227 228 229 230 231 232 233 234 235 | background: #fff; border: 1px solid #000; border-radius: 11px; padding-left: 4px; padding-right: 4px; line-height: 125%; } /* Container for an image */ .imgcontainer img { max-height: 100%; max-width: 100%; } | > > > > > > > | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | background: #fff; border: 1px solid #000; border-radius: 11px; padding-left: 4px; padding-right: 4px; line-height: 125%; } .yynonterm { background: #fff; border: 1px solid #000; padding-left: 2px; padding-right: 2px; line-height: 125%; } /* Container for an image */ .imgcontainer img { max-height: 100%; max-width: 100%; } |
︙ | ︙ |
Changes to search/hdom.tcl.
︙ | ︙ | |||
92 93 94 95 96 97 98 | # All inline tags. variable aInline foreach x { tt i b big small u em strong dfn code samp kbd var cite abbr acronym a img object br script map q sub sup span bdo | | | 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | # All inline tags. variable aInline foreach x { tt i b big small u em strong dfn code samp kbd var cite abbr acronym a img object br script map q sub sup span bdo input select textarea label button tcl yyterm yynonterm } { set aInline($x) 1 } # All self-closing tags (set below) variable aSelfClosing variable aContentChecker set aContentChecker(p) HtmlInlineContent |
︙ | ︙ |
Changes to wrap.tcl.
︙ | ︙ | |||
83 84 85 86 87 88 89 | # appropriate <a href=""> markup. # # Links to keywords within the same main file are resolved using # $::llink() if possible. All other links and links that could # not be resolved using $::llink() are resolved using $::glink(). # proc hd_resolve_2ndpass {text} { | | | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | # appropriate <a href=""> markup. # # Links to keywords within the same main file are resolved using # $::llink() if possible. All other links and links that could # not be resolved using $::llink() are resolved using $::glink(). # proc hd_resolve_2ndpass {text} { regsub -all {<(yy(non)?term)>} $text {<span class='\1'>} text regsub -all {</yy(non)?term>} $text {</span>} text regsub -all {\[(.*?)\]} $text \ "\175; hd_resolve_one \173\\1\175; hd_puts \173" text eval "hd_puts \173$text\175" } proc hd_resolve_one {x} { if {[string is integer $x] || [string length $x]==1} { hd_puts \[$x\] |
︙ | ︙ |