с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ произвСсти Π°Π²Ρ‚ΠΎΠ·Π°ΠΌΠ΅Π½Ρƒ null Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² postgresql

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ произвСсти Π°Π²Ρ‚ΠΎΠ·Π°ΠΌΠ΅Π½Ρƒ null Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² postgresql

ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π΄Π°ΡŽΡ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ вычислСния с Π½Π°Π±ΠΎΡ€ΠΎΠΌ строк, ΠΊΠ°ΠΊΠΈΠΌ-Π»ΠΈΠ±ΠΎ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ связанным с Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строкой запроса. Π’Π²ΠΎΠ΄Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎΠ± этом ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π² Π Π°Π·Π΄Π΅Π»Π΅ 3.5, Π° ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΡƒΠ·Π½Π°Ρ‚ΡŒ ΠΎ синтаксисС ΠΌΠΎΠΆΠ½ΠΎ Π² ΠŸΠΎΠ΄Ρ€Π°Π·Π΄Π΅Π»Π΅ 4.2.8.

Π’ Π΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊ этим функциям Π² качСствС ΠΎΠΊΠΎΠ½Π½Ρ‹Ρ… ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π»ΡŽΠ±Ρ‹Π΅ встроСнныС ΠΈΠ»ΠΈ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ (Π½ΠΎ Π½Π΅ ΡΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ ΠΈ Π½Π΅ Π³ΠΈΠΏΠΎΡ‚Π΅Π·ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅); список встроСнных Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½ Π² Π Π°Π·Π΄Π΅Π»Π΅ 9.21. АгрСгатныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΊΠ°ΠΊ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠΎΠ³Π΄Π° Π·Π° ΠΈΡ… Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ слСдуСт ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ OVER ; Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС ΠΎΠ½ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΊΠ°ΠΊ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ Π²Ρ‹Π΄Π°ΡŽΡ‚ для всСго Π½Π°Π±ΠΎΡ€Π° Π΅Π΄ΠΈΠ½ΡΡ‚Π²Π΅Π½Π½ΡƒΡŽ строку.

Π’Π°Π±Π»ΠΈΡ†Π° 9.60. ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΠ±Ρ‰Π΅Π³ΠΎ назначСния

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠΌΠ΅Ρ€ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строки Π² Π΅Ρ‘ Ρ€Π°Π·Π΄Π΅Π»Π΅, начиная с 1.

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π°Π½Π³ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строки с пропусками; Ρ‚ΠΎ ΠΆΠ΅, Ρ‡Ρ‚ΠΎ ΠΈ row_number для ΠΏΠ΅Ρ€Π²ΠΎΠΉ родствСнной Π΅ΠΉ строки.

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π°Π½Π³ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строки Π±Π΅Π· пропусков; ΠΏΠΎ сути эта функция считаСт Π³Ρ€ΡƒΠΏΠΏΡ‹ родствСнных строк.

percent_rank () β†’ double precision

cume_dist () β†’ double precision

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ кумулятивноС распрСдСлСниС, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ (число строк Ρ€Π°Π·Π΄Π΅Π»Π°, ΠΏΡ€Π΅Π΄ΡˆΠ΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΈΠ»ΠΈ родствСнных Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строкС) / (ΠΎΠ±Ρ‰Π΅Π΅ число строк Ρ€Π°Π·Π΄Π΅Π»Π°). Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π»Π΅ΠΆΠΈΡ‚ Π² ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»Π΅ ΠΎΡ‚ 1/ N Π΄ΠΎ 1.

ntile ( num_buckets integer ) β†’ integer

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ†Π΅Π»ΠΎΠ΅ ΠΎΡ‚ 1 Π΄ΠΎ значСния Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° для разбиСния Ρ€Π°Π·Π΄Π΅Π»Π° Π½Π° части максимально Π±Π»ΠΈΠ·ΠΊΠΈΡ… Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠ².

first_value ( value anyelement ) β†’ anyelement

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ( value ), вычислСнноС для ΠΏΠ΅Ρ€Π²ΠΎΠΉ строки Π² Ρ€Π°ΠΌΠΊΠ΅ ΠΎΠΊΠ½Π°.

last_value ( value anyelement ) β†’ anyelement

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ( value ), вычислСнноС для послСднСй строки Π² Ρ€Π°ΠΌΠΊΠ΅ ΠΎΠΊΠ½Π°.

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ

Π‘ ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ произвСсти Π°Π²Ρ‚ΠΎΠ·Π°ΠΌΠ΅Π½Ρƒ null Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² postgresql

ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π΄Π°ΡŽΡ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡ‚ΡŒ вычислСния с Π½Π°Π±ΠΎΡ€ΠΎΠΌ строк, ΠΊΠ°ΠΊΠΈΠΌ-Π»ΠΈΠ±ΠΎ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ связанным с Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строкой запроса. Π’Π²ΠΎΠ΄Π½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎΠ± этом ΠΌΠΎΠΆΠ½ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ Π² Π Π°Π·Π΄Π΅Π»Π΅ 3.5, Π° ΠΏΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΡƒΠ·Π½Π°Ρ‚ΡŒ ΠΎ синтаксисС ΠΌΠΎΠΆΠ½ΠΎ Π² ΠŸΠΎΠ΄Ρ€Π°Π·Π΄Π΅Π»Π΅ 4.2.8.

Π’ Π΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊ этим функциям Π² качСствС ΠΎΠΊΠΎΠ½Π½Ρ‹Ρ… ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π»ΡŽΠ±Ρ‹Π΅ встроСнныС ΠΈΠ»ΠΈ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Π΅ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ (Π½ΠΎ Π½Π΅ ΡΠΎΡ€Ρ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ ΠΈ Π½Π΅ Π³ΠΈΠΏΠΎΡ‚Π΅Π·ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅); список встроСнных Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΏΡ€ΠΈΠ²Π΅Π΄Ρ‘Π½ Π² Π Π°Π·Π΄Π΅Π»Π΅ 9.21. АгрСгатныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΊΠ°ΠΊ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅, Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊΠΎΠ³Π΄Π° Π·Π° ΠΈΡ… Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ слСдуСт ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ OVER ; Π² ΠΏΡ€ΠΎΡ‚ΠΈΠ²Π½ΠΎΠΌ случаС ΠΎΠ½ΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΊΠ°ΠΊ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ Π²Ρ‹Π΄Π°ΡŽΡ‚ для всСго Π½Π°Π±ΠΎΡ€Π° Π΅Π΄ΠΈΠ½ΡΡ‚Π²Π΅Π½Π½ΡƒΡŽ строку.

Π’Π°Π±Π»ΠΈΡ†Π° 9.60. ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΠ±Ρ‰Π΅Π³ΠΎ назначСния

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π½ΠΎΠΌΠ΅Ρ€ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строки Π² Π΅Ρ‘ Ρ€Π°Π·Π΄Π΅Π»Π΅, начиная с 1.

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π°Π½Π³ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строки с пропусками; Ρ‚ΠΎ ΠΆΠ΅, Ρ‡Ρ‚ΠΎ ΠΈ row_number для ΠΏΠ΅Ρ€Π²ΠΎΠΉ родствСнной Π΅ΠΉ строки.

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ€Π°Π½Π³ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строки Π±Π΅Π· пропусков; ΠΏΠΎ сути эта функция считаСт Π³Ρ€ΡƒΠΏΠΏΡ‹ родствСнных строк.

percent_rank () β†’ double precision

cume_dist () β†’ double precision

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ кумулятивноС распрСдСлСниС, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ (число строк Ρ€Π°Π·Π΄Π΅Π»Π°, ΠΏΡ€Π΅Π΄ΡˆΠ΅ΡΡ‚Π²ΡƒΡŽΡ‰ΠΈΡ… ΠΈΠ»ΠΈ родствСнных Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строкС) / (ΠΎΠ±Ρ‰Π΅Π΅ число строк Ρ€Π°Π·Π΄Π΅Π»Π°). Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π»Π΅ΠΆΠΈΡ‚ Π² ΠΈΠ½Ρ‚Π΅Ρ€Π²Π°Π»Π΅ ΠΎΡ‚ 1/ N Π΄ΠΎ 1.

ntile ( num_buckets integer ) β†’ integer

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ†Π΅Π»ΠΎΠ΅ ΠΎΡ‚ 1 Π΄ΠΎ значСния Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° для разбиСния Ρ€Π°Π·Π΄Π΅Π»Π° Π½Π° части максимально Π±Π»ΠΈΠ·ΠΊΠΈΡ… Ρ€Π°Π·ΠΌΠ΅Ρ€ΠΎΠ².

first_value ( value anyelement ) β†’ anyelement

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ( value ), вычислСнноС для ΠΏΠ΅Ρ€Π²ΠΎΠΉ строки Π² Ρ€Π°ΠΌΠΊΠ΅ ΠΎΠΊΠ½Π°.

last_value ( value anyelement ) β†’ anyelement

Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ( value ), вычислСнноС для послСднСй строки Π² Ρ€Π°ΠΌΠΊΠ΅ ΠΎΠΊΠ½Π°.

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ

3.5. ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ

Оконная функция выполняСт вычислСния для Π½Π°Π±ΠΎΡ€Π° строк, Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ связанных с Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строкой. МоТно ΡΡ€Π°Π²Π½ΠΈΡ‚ΡŒ Π΅Ρ‘ с Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ, Π½ΠΎ, Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΉ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΏΡ€ΠΈ использовании ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ нСсколько строк Π½Π΅ Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΡƒΡŽΡ‚ΡΡ Π² ΠΎΠ΄Π½Ρƒ, Π° ΠΏΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ°ΡŽΡ‚ ΡΡƒΡ‰Π΅ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ. Π’Π½ΡƒΡ‚Ρ€ΠΈ ΠΆΠ΅, оконная функция, ΠΊΠ°ΠΊ ΠΈ агрСгатная, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΊ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строкС Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° запроса.

Π’ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ, ΠΊΠ°ΠΊ ΡΡ€Π°Π²Π½ΠΈΡ‚ΡŒ Π·Π°Ρ€ΠΏΠ»Π°Ρ‚Ρƒ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ сотрудника со срСднСй Π·Π°Ρ€ΠΏΠ»Π°Ρ‚ΠΎΠΉ Π΅Π³ΠΎ ΠΎΡ‚Π΄Π΅Π»Π°:

Π’Ρ‹Π·ΠΎΠ² ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ всСгда содСрТит ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ OVER, ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅Π΅ Π·Π° Π½Π°Π·Π²Π°Π½ΠΈΠ΅ΠΌ ΠΈ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°ΠΌΠΈ ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. Π­Ρ‚ΠΎ синтаксичСски ΠΎΡ‚Π»ΠΈΡ‡Π°Π΅Ρ‚ Π΅Ρ‘ ΠΎΡ‚ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΉ ΠΈΠ»ΠΈ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. ΠŸΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ OVER опрСдСляСт, ΠΊΠ°ΠΊ ΠΈΠΌΠ΅Π½Π½ΠΎ Π½ΡƒΠΆΠ½ΠΎ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚ΡŒ строки запроса для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ. ΠŸΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ PARTITION BY, Π΄ΠΎΠΏΠΎΠ»Π½ΡΡŽΡ‰Π΅Π΅ OVER, ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ строки Π½ΡƒΠΆΠ½ΠΎ Ρ€Π°Π·Π΄Π΅Π»ΠΈΡ‚ΡŒ ΠΏΠΎ Π³Ρ€ΡƒΠΏΠΏΠ°ΠΌ ΠΈΠ»ΠΈ Ρ€Π°Π·Π΄Π΅Π»Π°ΠΌ, объСдиняя ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Π΅ значСния Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ PARTITION BY. Оконная функция вычисляСтся ΠΏΠΎ строкам, ΠΏΠΎΠΏΠ°Π΄Π°ΡŽΡ‰ΠΈΠΌ Π² ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·Π΄Π΅Π» с Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строкой.

Π’Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ Ρ‚Π°ΠΊΠΆΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ порядок, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ строки Π±ΡƒΠ΄ΡƒΡ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒΡΡ ΠΎΠΊΠΎΠ½Π½Ρ‹ΠΌΠΈ функциями, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ORDER BY Π² OVER. (ΠŸΠΎΡ€ΡΠ΄ΠΎΠΊ ORDER BY для ΠΎΠΊΠ½Π° ΠΌΠΎΠΆΠ΅Ρ‚ Π΄Π°ΠΆΠ΅ Π½Π΅ ΡΠΎΠ²ΠΏΠ°Π΄Π°Ρ‚ΡŒ с порядком, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ выводятся строки.) НапримСр:

Как ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ здСсь, функция rank Π²Ρ‹Π΄Π°Ρ‘Ρ‚ порядковый Π½ΠΎΠΌΠ΅Ρ€ Π² Ρ€Π°Π·Π΄Π΅Π»Π΅ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строки для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΡƒΠ½ΠΈΠΊΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ значСния, ΠΏΠΎ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ выполняСт сортировку ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ORDER BY. Π£ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ rank Π½Π΅Ρ‚ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠ², Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Π΅Ρ‘ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ опрСдСляСтся ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ΠΌ OVER.

ΠœΡ‹ ΡƒΠΆΠ΅ Π²ΠΈΠ΄Π΅Π»ΠΈ, Ρ‡Ρ‚ΠΎ ORDER BY ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ, Ссли порядок строк Π½Π΅ Π²Π°ΠΆΠ΅Π½. Π’Π°ΠΊΠΆΠ΅ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ PARTITION BY, Π² этом случаС Π±ΡƒΠ΄Π΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·Π΄Π΅Π», содСрТащий всС строки.

Π•ΡΡ‚ΡŒ Π΅Ρ‰Ρ‘ ΠΎΠ΄Π½ΠΎ Π²Π°ΠΆΠ½ΠΎΠ΅ понятиС, связанноС с ΠΎΠΊΠΎΠ½Π½Ρ‹ΠΌΠΈ функциями: для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки сущСствуСт Π½Π°Π±ΠΎΡ€ строк Π² Π΅Ρ‘ Ρ€Π°Π·Π΄Π΅Π»Π΅, Π½Π°Π·Ρ‹Π²Π°Π΅ΠΌΡ‹ΠΉ Ρ€Π°ΠΌΠΊΠΎΠΉ ΠΎΠΊΠ½Π°. По ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ΠΌ ORDER BY Ρ€Π°ΠΌΠΊΠ° состоит ΠΈΠ· всСх строк ΠΎΡ‚ Π½Π°Ρ‡Π°Π»Π° Ρ€Π°Π·Π΄Π΅Π»Π° Π΄ΠΎ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строки ΠΈ строк, Ρ€Π°Π²Π½Ρ‹Ρ… Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ ΠΏΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ выраТСния ORDER BY. Π‘Π΅Π· ORDER BY Ρ€Π°ΠΌΠΊΠ° ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ состоит ΠΈΠ· всСх строк Ρ€Π°Π·Π΄Π΅Π»Π°. [1] ΠŸΠΎΡΠΌΠΎΡ‚Ρ€ΠΈΡ‚Π΅ Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€ использования sum :

Π’Π°ΠΊ ΠΊΠ°ΠΊ Π² этом ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ Π½Π΅Ρ‚ указания ORDER BY Π² ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠΈ OVER, Ρ€Π°ΠΌΠΊΠ° ΠΎΠΊΠ½Π° содСрТит всС строки Ρ€Π°Π·Π΄Π΅Π»Π°, Π° ΠΎΠ½, Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ, Π±Π΅Π· прСдлоТСния PARTITION BY Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ всС строки Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹; Π΄Ρ€ΡƒΠ³ΠΈΠΌΠΈ словами, сумма вычисляСтся ΠΏΠΎ всСй Ρ‚Π°Π±Π»ΠΈΡ†Π΅ ΠΈ ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅ΠΌ ΠΎΠ΄ΠΈΠ½ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°. Но Ссли ΠΌΡ‹ Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ORDER BY, ΠΌΡ‹ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠΌ совсСм Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Ρ‹:

Π—Π΄Π΅ΡΡŒ Π² суммС Π½Π°ΠΊΠ°ΠΏΠ»ΠΈΠ²Π°ΡŽΡ‚ΡΡ Π·Π°Ρ€ΠΏΠ»Π°Ρ‚Ρ‹ ΠΎΡ‚ ΠΏΠ΅Ρ€Π²ΠΎΠΉ (самой Π½ΠΈΠ·ΠΊΠΎΠΉ) Π΄ΠΎ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ ΠΏΠΎΠ²Ρ‚ΠΎΡ€ΡΡŽΡ‰ΠΈΠ΅ΡΡ Ρ‚Π΅ΠΊΡƒΡ‰ΠΈΠ΅ значСния (ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π² строках с ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎΠΉ Π·Π°Ρ€ΠΏΠ»Π°Ρ‚ΠΎΠΉ).

ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ΡΡ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² запросС Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π² спискС SELECT ΠΈ ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠΈ ORDER BY. Π’ΠΎ всСх ΠΎΡΡ‚Π°Π»ΡŒΠ½Ρ‹Ρ… прСдлоТСниях, Π²ΠΊΠ»ΡŽΡ‡Π°Ρ GROUP BY, HAVING ΠΈ WHERE, ΠΎΠ½ΠΈ Π·Π°ΠΏΡ€Π΅Ρ‰Π΅Π½Ρ‹. Π­Ρ‚ΠΎ ΠΎΠ±ΡŠΡΡΠ½ΡΠ΅Ρ‚ΡΡ Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ логичСски ΠΎΠ½ΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ послС ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹Ρ… Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, Π° Π·Π½Π°Ρ‡ΠΈΡ‚ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ ΠΈΠ· ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ, Π½ΠΎ Π½Π΅ Π½Π°ΠΎΠ±ΠΎΡ€ΠΎΡ‚.

Если Π²Π°ΠΌ Π½ΡƒΠΆΠ½ΠΎ ΠΎΡ‚Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΈΠ»ΠΈ ΡΠ³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ строки послС вычислСния ΠΎΠΊΠΎΠ½Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, Π²Ρ‹ ΠΌΠΎΠΆΠ΅Ρ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π²Π»ΠΎΠΆΠ΅Π½Π½Ρ‹ΠΉ запрос. НапримСр:

Π”Π°Π½Π½Ρ‹ΠΉ запрос ΠΏΠΎΠΊΠ°ΠΆΠ΅Ρ‚ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚Π΅ строки Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ запроса, Ρƒ ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… rank (порядковый Π½ΠΎΠΌΠ΅Ρ€) мСньшС 3.

Когда Π² запросС Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΡŽΡ‚ΡΡ нСсколько ΠΎΠΊΠΎΠ½Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ для ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Ρ‘Π½Π½Ρ‹Ρ… ΠΎΠΊΠΎΠ½, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΈΠ· Π½ΠΈΡ… ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠ΅ ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ OVER, Π½ΠΎ ΠΏΡ€ΠΈ этом ΠΎΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Π΄ΡƒΠ±Π»ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ, Ρ‡Ρ‚ΠΎ Π½Π΅ΠΈΠ·Π±Π΅ΠΆΠ½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΎΠ²ΠΎΡ†ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ошибки. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Π»ΡƒΡ‡ΡˆΠ΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ ΠΎΠΊΠ½Π° Π²Ρ‹Π΄Π΅Π»ΠΈΡ‚ΡŒ Π² ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ WINDOW, Π° Π·Π°Ρ‚Π΅ΠΌ ΡΡΡ‹Π»Π°Ρ‚ΡŒΡΡ Π½Π° Π½Π΅Π³ΠΎ Π² OVER. НапримСр:

ΠŸΠΎΠ΄Ρ€ΠΎΠ±Π½Π΅Π΅ ΠΎΠ± ΠΎΠΊΠΎΠ½Π½Ρ‹Ρ… функциях ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ·Π½Π°Ρ‚ΡŒ Π² ΠŸΠΎΠ΄Ρ€Π°Π·Π΄Π΅Π»Π΅ 4.2.8, Π Π°Π·Π΄Π΅Π»Π΅ 9.21, ΠŸΠΎΠ΄Ρ€Π°Π·Π΄Π΅Π»Π΅ 7.2.4 ΠΈ Π² справкС SELECT.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ

Как ΠΏΠΎΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ всё Π½Π° свСтС ΠΎΠ΄Π½ΠΈΠΌ SQL-запросом. ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ PostgreSQL

с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ произвСсти Π°Π²Ρ‚ΠΎΠ·Π°ΠΌΠ΅Π½Ρƒ null Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² postgresql. Π‘ΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ Ρ„ΠΎΡ‚ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ произвСсти Π°Π²Ρ‚ΠΎΠ·Π°ΠΌΠ΅Π½Ρƒ null Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² postgresql. Π‘ΠΌΠΎΡ‚Ρ€Π΅Ρ‚ΡŒ ΠΊΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΡƒ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ произвСсти Π°Π²Ρ‚ΠΎΠ·Π°ΠΌΠ΅Π½Ρƒ null Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² postgresql. ΠšΠ°Ρ€Ρ‚ΠΈΠ½ΠΊΠ° ΠΏΡ€ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ произвСсти Π°Π²Ρ‚ΠΎΠ·Π°ΠΌΠ΅Π½Ρƒ null Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² postgresql. Π€ΠΎΡ‚ΠΎ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠ°ΠΊΠΎΠΉ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ ΠΌΠΎΠΆΠ½ΠΎ произвСсти Π°Π²Ρ‚ΠΎΠ·Π°ΠΌΠ΅Π½Ρƒ null Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² postgresql

Π― с ΡƒΠ΄ΠΈΠ²Π»Π΅Π½ΠΈΠ΅ΠΌ ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΠ», Ρ‡Ρ‚ΠΎ ΠΌΠ½ΠΎΠ³ΠΈΠ΅ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚Ρ‡ΠΈΠΊΠΈ, Π΄Π°ΠΆΠ΅ Π΄Π°Π²Π½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡŽΡ‰ΠΈΠ΅ postgresql, Π½Π΅ ΠΏΠΎΠ½ΠΈΠΌΠ°ΡŽΡ‚ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, считая ΠΈΡ… ΠΊΠ°ΠΊΠΎΠΉ-Ρ‚ΠΎ особой ΠΌΠ°Π³ΠΈΠ΅ΠΉ для ΠΈΠ·Π±Ρ€Π°Π½Π½Ρ‹Ρ…. Ну ΠΈΠ»ΠΈ Π² Π»ΡƒΡ‡ΡˆΠ΅ΠΌ случаС «копипастят» со StackOverflow выраТСния Ρ‚ΠΈΠΏΠ° Β«row_number() OVER ()Β», Π½Π΅ вдаваясь Π² Π΄Π΅Ρ‚Π°Π»ΠΈ. А вСдь ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ β€” полСзнСйший Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π» PostgreSQL.
ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΡŽ ΠΏΠΎ-простому ΠΎΠ±ΡŠΡΡΠ½ΠΈΡ‚ΡŒ, ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡ… ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ.

Для Π½Π°Ρ‡Π°Π»Π° Ρ…ΠΎΡ‡Ρƒ сразу ΠΏΠΎΡΡΠ½ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π΅ ΠΈΠ·ΠΌΠ΅Π½ΡΡŽΡ‚ Π²Ρ‹Π±ΠΎΡ€ΠΊΡƒ, Π° Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ ΠΎ Π½Π΅ΠΉ. Π’.Π΅. для простоты понимания ΠΌΠΎΠΆΠ½ΠΎ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ postgres сначала выполняСт вСсь запрос (ΠΊΡ€ΠΎΠΌΠ΅ сортировки ΠΈ limit), Π° ΠΏΠΎΡ‚ΠΎΠΌ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ просчитываСт ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ выраТСния.

Бинтаксис ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Ρ‚Π°ΠΊΠΎΠΉ:

Окно β€” это Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, ΠΎΠΏΠΈΡΡ‹Π²Π°ΡŽΡ‰Π΅Π΅ Π½Π°Π±ΠΎΡ€ строк, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ функция ΠΈ порядок этой ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ.
ΠŸΡ€ΠΈΡ‡Π΅ΠΌ ΠΎΠΊΠ½ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ просто Π·Π°Π΄Π°Π½ΠΎ пустыми скобками (), Ρ‚.Π΅. ΠΎΠΊΠ½ΠΎΠΌ ΡΠ²Π»ΡΡŽΡ‚ΡΡ всС строки Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° запроса.

НапримСр, Π² этом сСлСктС ΠΊ ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΌ полям id, header ΠΈ score просто добавится нумСрация строк.

Π’ ΠΎΠΊΠΎΠ½Π½ΠΎΠ΅ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ORDER BY, Ρ‚ΠΎΠ³Π΄Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΈΠ·ΠΌΠ΅Π½ΠΈΡ‚ΡŒ порядок ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ я Π΄ΠΎΠ±Π°Π²ΠΈΠ» Π΅Ρ‰Π΅ ΠΈ Π² ΠΊΠΎΠ½Ρ†Π΅ всСго запоса ORDER BY id, ΠΏΡ€ΠΈ этом Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³ посчитан всС Ρ€Π°Π²Π½ΠΎ Π²Π΅Ρ€Π½ΠΎ. Π’.Π΅. посгрСс просто отсортировал Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ вмСстС с Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠΌ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΠΎΠ΄ΠΈΠ½ order Π½ΠΈΡ‡ΡƒΡ‚ΡŒ Π½Π΅ ΠΌΠ΅ΡˆΠ°Π΅Ρ‚ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ.

Π”Π°Π»ΡŒΡˆΠ΅ β€” большС. Π’ ΠΎΠΊΠΎΠ½Π½ΠΎΠ΅ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ слово PARTITION BY [expression],
Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€ row_number() OVER (PARTITION BY section), Ρ‚ΠΎΠ³Π΄Π° подсчСт Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠ΄Ρ‚ΠΈ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π³Ρ€ΡƒΠΏΠΏΠ΅ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ:

Если Π½Π΅ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Ρ‚ΡŒ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΡŽ, Ρ‚ΠΎ ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠ΅ΠΉ являСтся вСсь запрос.

Π’ΡƒΡ‚ сразу Π½Π°Π΄ΠΎ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΎ функциях, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ Π΅ΡΡ‚ΡŒ ΠΎΡ‡Π΅Π½ΡŒ Π²Π°ΠΆΠ½Ρ‹ΠΉ нюанс.
Π’ качСствС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ, Ρ‚Π°ΠΊ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ, истинныС ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈΠ· ΠΌΠ°Π½ΡƒΠ°Π»Π° β€” это row_number(), rank(), lead() ΠΈ Ρ‚.Π΄., Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ-Π°Π³Ρ€Π΅Π³Π°Ρ‚Ρ‹, Ρ‚Π°ΠΊΠΈΠ΅ ΠΊΠ°ΠΊ: sum(), count() ΠΈ Ρ‚.Π΄. Π’Π°ΠΊ Π²ΠΎΡ‚, это Π²Π°ΠΆΠ½ΠΎ, Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ слСгка ΠΏΠΎ-Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ: Ссли Π½Π΅ Π·Π°Π΄Π°Π½ ORDER BY Π² ΠΎΠΊΠ½Π΅, ΠΈΠ΄Π΅Ρ‚ подсчСт ΠΏΠΎ всСй ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·, ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΏΠΈΡˆΠ΅Ρ‚ΡΡ Π²ΠΎ всС строки (ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ² для всСх строк ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ). Если ΠΆΠ΅ ORDER BY Π·Π°Π΄Π°Π½, Ρ‚ΠΎ подсчСт Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строкС ΠΈΠ΄Π΅Ρ‚ ΠΎΡ‚ Π½Π°Ρ‡Π°Π»Π° ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ Π΄ΠΎ этой строки.

Π”Π°Π²Π°ΠΉΡ‚Π΅ посмотрим это Π½Π° ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅. НапримСр, Ρƒ нас Π΅ΡΡ‚ΡŒ нСкая (сфСричСская Π² Π²Π°ΠΊΡƒΡƒΠΌΠ΅) Ρ‚Π°Π±Π»ΠΈΡ†Π° ΠΏΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΉ балансов.

ΠΈ ΠΌΡ‹ Ρ…ΠΎΡ‚ΠΈΠΌ ΡƒΠ·Π½Π°Ρ‚ΡŒ Π·Π°ΠΎΠ΄Π½ΠΎ, ΠΊΠ°ΠΊ мСнялся остаток Π½Π° балансС ΠΏΡ€ΠΈ этом:

Π’.Π΅. для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки ΠΈΠ΄Π΅Ρ‚ подсчСт Π² ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΌ Ρ„Ρ€Π΅ΠΉΠΌΠ΅. Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС Ρ„Ρ€Π΅ΠΉΠΌ β€” это Π½Π°Π±ΠΎΡ€ строк ΠΎΡ‚ Π½Π°Ρ‡Π°Π»Π° Π΄ΠΎ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ строки (Ссли Π±Ρ‹Π»ΠΎ Π±Ρ‹ PARTITION BY, Ρ‚ΠΎ ΠΎΡ‚ Π½Π°Ρ‡Π°Π»Π° ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ).

Если ΠΆΠ΅ ΠΌΡ‹ для Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΠΎΠΉ Ρ„ΡƒΠ½Ρ†ΠΈΠΈ sum Π½Π΅ Π±ΡƒΠ΄Π΅ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ORDER BY Π² ΠΎΠΊΠ½Π΅, Ρ‚ΠΎΠ³Π΄Π° ΠΌΡ‹ просто посчитаСм ΠΎΠ±Ρ‰ΡƒΡŽ сумму ΠΈ ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ Π΅Ρ‘ Π²ΠΎ всСх строках. Π’.Π΅. Ρ„Ρ€Π΅ΠΉΠΌΠΎΠΌ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ ΠΈΠ· строк Π±ΡƒΠ΄Π΅Ρ‚ вСсь Π½Π°Π±ΠΎΡ€ строк
ΠΎΡ‚ Π½Π°Ρ‡Π°Π»Π° Π΄ΠΎ ΠΊΠΎΠ½Ρ†Π° ΠΏΠ°Ρ€Ρ‚ΠΈΡ†ΠΈΠΈ.

Π’ΠΎΡ‚ такая ΠΎΡΠΎΠ±Π΅Π½Π½ΠΎΡΡ‚ΡŒ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, Ссли ΠΈΡ… ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΊΠ°ΠΊ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅. На ΠΌΠΎΠΉ взгляд, это довольно-Ρ‚Π°ΠΊΠΈ странный, ΠΈΠ½Ρ‚ΡƒΠΈΡ‚ΠΈΠ²Π½ΠΎ Π½Π΅ΠΎΡ‡Π΅Π²ΠΈΠ΄Π½Ρ‹ΠΉ ΠΌΠΎΠΌΠ΅Π½Ρ‚ SQL-стандарта.

ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ сразу ΠΏΠΎ нСсколько ΡˆΡ‚ΡƒΠΊ, ΠΎΠ½ΠΈ Π΄Ρ€ΡƒΠ³ Π΄Ρ€ΡƒΠ³Ρƒ Π½ΠΈΡ‡ΡƒΡ‚ΡŒ Π½Π΅ ΠΌΠ΅ΡˆΠ°ΡŽΡ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹ Ρ‚Π°ΠΌ Π² Π½ΠΈΡ… Π½Π΅ написали.

Если Ρƒ вас ΠΌΠ½ΠΎΠ³ΠΎ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²Ρ‹Ρ… Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠΉ послС OVER, Ρ‚ΠΎ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π°Ρ‚ΡŒ ΠΈΠΌ имя ΠΈ вынСсти ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ с ΠΊΠ»ΡŽΡ‡Π΅Π²Ρ‹ΠΌ словом WINDOW, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ дублирования ΠΊΠΎΠ΄Π°. Π’ΠΎΡ‚ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΈΠ· ΠΌΠ°Π½ΡƒΠ°Π»Π°:

Π—Π΄Π΅ΡΡŒ w послС слова OVER ΠΈΠ΄Π΅Ρ‚ Π±Π΅Π· ΡƒΠΆΠ΅ скобок.

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π½Π΅Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎ ΠΎΡ‚Ρ„ΠΈΠ»ΡŒΡ‚Ρ€ΠΎΠ²Π°Ρ‚ΡŒ Π² запросС с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ WHERE, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½Ρ†ΠΈΠΈ Π²Ρ‹ΠΏΠΎΠ»Π½ΡΡŽΡ‚ΡΡ послС всСй Ρ„ΠΈΠ»ΡŒΡ‚Ρ€Π°Ρ†ΠΈΠΈ ΠΈ Π³Ρ€ΡƒΠΏΠΏΠΈΡ€ΠΎΠ²ΠΊΠΈ, Ρ‚.Π΅. с Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΠ»ΠΎΡΡŒ. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ‚ΠΎΠΏ 5 новостСй Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π³Ρ€ΡƒΠΏΠΏΠ΅, Π½Π°Π΄ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ подзапрос:

Π•Ρ‰Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ для закрСплСния. Помимо row_number() Π΅ΡΡ‚ΡŒ нСсколько Π΄Ρ€ΡƒΠ³ΠΈΡ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ. НапримСр lag, которая ΠΈΡ‰Π΅Ρ‚ строку ΠΏΠ΅Ρ€Π΅Π΄ послСднСй строкой Ρ„Ρ€Π΅ΠΉΠΌΠ°. К ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρƒ ΠΌΡ‹ ΠΌΠΎΠΆΠ΅ΠΌ Π½Π°ΠΉΡ‚ΠΈ насколько ΠΎΡ‡ΠΊΠΎΠ² Π½ΠΎΠ²ΠΎΡΡ‚ΡŒ отстаСт ΠΎΡ‚ ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰Π΅ΠΉ Π² Ρ€Π΅ΠΉΡ‚ΠΈΠ½Π³Π΅:

ΠŸΡ€ΠΎΡˆΡƒ Π² комСнтариях Π½Π°ΠΊΠΈΠ΄Π°Ρ‚ΡŒ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ΠΎΠ², Π³Π΄Π΅ особСнно ΡƒΠ΄ΠΎΠ±Π½ΠΎ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½Ρ†ΠΈΠΈ. А Ρ‚Π°ΠΊΠΆΠ΅, ΠΊΠ°ΠΊΠΈΠ΅ с Π½ΠΈΠΌΠΈ ΠΌΠΎΠ³ΡƒΡ‚ Π²ΠΎΠ·Π½ΠΈΠΊΠ½ΡƒΡ‚ΡŒ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, Ссли Ρ‚Π°ΠΊΠΎΠ²Ρ‹Π΅ ΠΈΠΌΠ΅ΡŽΡ‚ΡΡ.

ΠŸΠΎΠ΄ΠΏΠΈΡΡ‹Π²Π°ΠΉΡ‚Π΅ΡΡŒ Π½Π° подкаст ΠΎ Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅ «Π¦ΠΈΠ½ΠΊΠΎΠ²Ρ‹ΠΉ ΠΏΡ€ΠΎΠ΄», Π³Π΄Π΅ ΠΌΡ‹ обсуТдаСм Π±Π°Π·Ρ‹ Π΄Π°Π½Π½Ρ‹Ρ…, языки программирования ΠΈ всё Π½Π° свСтС!

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ

ΠŸΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Π΅ ΠΈ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² PostgreSQL ΠΈ Oracle

Π’ этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ ΠΌΡ‹ посмотрим, ΠΊΠ°ΠΊ Π² Π΄Π²ΡƒΡ… систСмах ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠ΅ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Π΅ ΠΈ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ (Π² Ρ‚Π΅Ρ€ΠΌΠΈΠ½ΠΎΠ»ΠΎΠ³ΠΈΠΈ Oracle β€” аналитичСскиС) Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. НСсмотря Π½Π° различия Π² синтаксисС ΠΈ Π² Ρ†Π΅Π»ΠΎΠΌ Π² ΠΏΠΎΠ΄Ρ…ΠΎΠ΄Π΅ ΠΊ Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅ΠΌΠΎΡΡ‚ΠΈ, ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌ этих Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ ΠΎΡ‡Π΅Π½ΡŒ ΠΏΠΎΡ…ΠΎΠΆ. Но ΠΈ различия Ρ‚ΠΎΠΆΠ΅ ΠΈΠΌΠ΅ΡŽΡ‚ΡΡ.

Надо ΠΏΡ€ΠΈΠ·Π½Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎ собствСнныС Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Π΅ ΠΈ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ встрСчаСтся довольно Ρ€Π΅Π΄ΠΊΠΎ. ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²ΠΎΠΎΠ±Ρ‰Π΅ ΠΏΠΎ ΠΊΠ°ΠΊΠΈΠΌ-Ρ‚ΠΎ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π°ΠΌ Ρ‚Ρ€Π°Π΄ΠΈΡ†ΠΈΠΎΠ½Π½ΠΎ относят ΠΊ разряду Β«ΠΏΡ€ΠΎΠ΄Π²ΠΈΠ½ΡƒΡ‚ΠΎΠ³ΠΎΒ» SQL ΠΈ ΡΡ‡ΠΈΡ‚Π°ΡŽΡ‚ слоТными для понимания ΠΈ освоСния. Π’ΡƒΡ‚ Π±Ρ‹ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Ρ‚ΡŒΡΡ с Ρ‚Π΅ΠΌΠΈ функциями, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΡƒΠΆΠ΅ ΠΈΠΌΠ΅ΡŽΡ‚ΡΡ Π² Π‘Π£Π‘Π”!

Π—Π°Ρ‡Π΅ΠΌ Ρ‚ΠΎΠ³Π΄Π° Π²ΠΎΠΎΠ±Ρ‰Π΅ Π²Π½ΠΈΠΊΠ°Ρ‚ΡŒ Π² этот вопрос? ΠœΠΎΠ³Ρƒ Π½Π°Π·Π²Π°Ρ‚ΡŒ нСсколько ΠΏΡ€ΠΈΡ‡ΠΈΠ½:

АгрСгатныС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ

Π‘ΡƒΠ΄Π΅ΠΌ Π΄Π²ΠΈΠ³Π°Ρ‚ΡŒΡΡ ΠΎΡ‚ простого ΠΊ слоТному, ΠΏΠ΅Ρ€Π΅ΠΊΠ»ΡŽΡ‡Π°ΡΡΡŒ ΠΌΠ΅ΠΆΠ΄Ρƒ PostgreSQL ΠΈ Oracle.

Π’Π½Π°Ρ‡Π°Π»Π΅ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΎΠ±Ρ‰ΠΈΠ΅ сообраТСния. Π›ΡŽΠ±Π°Ρ агрСгатная функция вызываСтся для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ ΠΏΠΎ ΠΎΡ‡Π΅Ρ€Π΅Π΄ΠΈ ΠΈ Π² ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎΠΌ ΠΈΡ‚ΠΎΠ³Π΅ ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ ΠΈΡ… всС. ΠœΠ΅ΠΆΠ΄Ρƒ Π²Ρ‹Π·ΠΎΠ²Π°ΠΌΠΈ Π΅ΠΉ трСбуСтся ΡΠΎΡ…Ρ€Π°Π½ΡΡ‚ΡŒ Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π΅ состояниС, ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰Π΅Π΅ контСкст Π΅Π΅ выполнСния. Π’ ΠΊΠΎΠ½Ρ†Π΅ Ρ€Π°Π±ΠΎΡ‚Ρ‹ ΠΎΠ½Π° Π΄ΠΎΠ»ΠΆΠ½Π° Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒ ΠΈΡ‚ΠΎΠ³ΠΎΠ²ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅.

Π˜Ρ‚Π°ΠΊ, Π½Π°ΠΌ потрСбуСтся Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅ ΡΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‰ΠΈΠ΅:

PostgreSQL

Для хранСния состояния Π½ΡƒΠΆΠ½ΠΎ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ подходящий Ρ‚ΠΈΠΏ Π΄Π°Π½Π½Ρ‹Ρ…. МоТно Π²Π·ΡΡ‚ΡŒ стандартный, Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ свой. Для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΡŽΡ‰Π΅ΠΉ срСднСС, Π½ΡƒΠΆΠ½ΠΎ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ ΡΡƒΠΌΠΌΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ значСния ΠΈ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ ΠΏΠΎΠ΄ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΈΡ… количСство. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ создадим свой составной Ρ‚ΠΈΠΏ с двумя полями:

CREATE TYPE average_state AS (
accum numeric,
qty numeric
);

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠ³ΠΎ значСния. Π’ PostgreSQL ΠΎΠ½Π° называСтся Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π°:

ΠšΡ€ΠΎΠΌΠ΅ этого, ΠΌΡ‹ Π²Ρ‹Π²ΠΎΠ΄ΠΈΠΌ (RAISE NOTICE) ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ β€” это ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈΡ‚ Π½Π°ΠΌ ΡƒΠ²ΠΈΠ΄Π΅Ρ‚ΡŒ, ΠΊΠ°ΠΊ выполняСтся Ρ€Π°Π±ΠΎΡ‚Π°. Π‘Ρ‚Π°Ρ€Ρ‹ΠΉ Π΄ΠΎΠ±Ρ€Ρ‹ΠΉ ΠΎΡ‚Π»Π°Π΄ΠΎΡ‡Π½Ρ‹ΠΉ PRINT, Π½Π΅Ρ‚ Π½ΠΈΡ‡Π΅Π³ΠΎ тСбя Π»ΡƒΡ‡ΡˆΠ΅.

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰Π°Ρ функция β€” Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ Ρ„ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ значСния:

Β«Π€ΠΈΠ½Ρ‚ ΡƒΡˆΠ°ΠΌΠΈΒ» с Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ trim Π½ΡƒΠΆΠ΅Π½ ΠΈΡΠΊΠ»ΡŽΡ‡ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ для аккуратности Π²Ρ‹Π²ΠΎΠ΄Π°: Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ ΠΌΡ‹ избавляСмся ΠΎΡ‚ Π½Π΅Π·Π½Π°Ρ‡Π°Ρ‰ΠΈΡ… Π½ΡƒΠ»Π΅ΠΉ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΠ½Π°Ρ‡Π΅ Π±ΡƒΠ΄ΡƒΡ‚ Π·Π°Π³Ρ€ΠΎΠΌΠΎΠΆΠ΄Π°Ρ‚ΡŒ экран ΠΈ ΠΌΠ΅ΡˆΠ°Ρ‚ΡŒ Π²ΠΎΡΠΏΡ€ΠΈΡΡ‚ΠΈΡŽ. ΠŸΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ Π²ΠΎΡ‚ Ρ‚Π°ΠΊ:

SELECT 1::numeric / 2::numeric;
?column?
————————
0.50000000000000000000
(1 row)

Π’ Ρ€Π΅Π°Π»ΡŒΠ½ΠΎΠΉ ΠΆΠΈΠ·Π½ΠΈ эти фокусы, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ, Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹.

И, Π½Π°ΠΊΠΎΠ½Π΅Ρ†, опрСдСляСм собствСнно Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ. Для этого ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΡΠΏΠ΅Ρ†ΠΈΠ°Π»ΡŒΠ½Π°Ρ ΠΊΠΎΠΌΠ°Π½Π΄Π° CREATE AGGREGATE:

МоТно ΠΏΡ€ΠΎΠ±ΠΎΠ²Π°Ρ‚ΡŒ. ΠŸΠΎΡ‡Ρ‚ΠΈ всС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π² этой ΡΡ‚Π°Ρ‚ΡŒΠ΅ Π±ΡƒΠ΄ΡƒΡ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡΡ‚ΡƒΡŽ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ с ΠΏΡΡ‚ΡŒΡŽ строками: Ρ€Π°Π·, Π΄Π²Π°, Ρ‚Ρ€ΠΈ, Ρ‡Π΅Ρ‚Ρ‹Ρ€Π΅, ΠΏΡΡ‚ΡŒ. Π’Π°Π±Π»ΠΈΡ†Ρƒ создаСм Π½Π° Π»Π΅Ρ‚Ρƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ generate_series, Π½Π΅Π·Π°ΠΌΠ΅Π½ΠΈΠΌΡ‹ΠΌ ΠΏΠΎΠΌΠΎΡ‰Π½ΠΈΠΊΠΎΠΌ Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ тСстовых Π΄Π°Π½Π½Ρ‹Ρ…:

SELECT average(g.x) FROM generate_series(1,5) AS g(x);
NOTICE: 0(0) + 1
NOTICE: 1(1) + 2
NOTICE: 3(2) + 3
NOTICE: 6(3) + 4
NOTICE: 10(4) + 5
NOTICE: = 15(5)
average
———
3
(1 row)

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π²Π΅Ρ€Π½Ρ‹ΠΉ, Π° Π²Ρ‹Π²ΠΎΠ΄ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ позволяСт ΠΏΡ€ΠΎΡΠ»Π΅Π΄ΠΈΡ‚ΡŒ Ρ…ΠΎΠ΄ выполнСния:

SELECT average(g.x) FROM generate_series(1,0) AS g(x);
NOTICE: = 0(0)
average
———

Oracle

Π’ Oracle вся Ρ€Π°ΡΡˆΠΈΡ€ΡΠ΅ΠΌΠΎΡΡ‚ΡŒ обСспСчиваСтся ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠΎΠΌ Data Cartridge. Говоря ΠΏΠΎ-простому, Π½Π°ΠΌ потрСбуСтся ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π½Ρ‹ΠΉ Ρ‚ΠΈΠΏ, Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΡŽΡ‰ΠΈΠΉ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΡ‹ΠΉ для Π°Π³Ρ€Π΅Π³Π°Ρ†ΠΈΠΈ интСрфСйс. ΠšΠΎΠ½Ρ‚Π΅ΠΊΡΡ‚ СстСствСнным ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ прСдставляСтся Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Π°ΠΌΠΈ этого ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.

CREATE OR REPLACE TYPE AverageImpl AS OBJECT(
accum number,
qty number,
STATIC FUNCTION ODCIAggregateInitialize (actx IN OUT AverageImpl)
RETURN number,
MEMBER FUNCTION ODCIAggregateIterate (self IN OUT AverageImpl, val IN number
RETURN number,
MEMBER FUNCTION ODCIAggregateMerge (self IN OUT AverageImpl, ctx2 IN AverageImpl)
RETURN number,
MEMBER FUNCTION ODCIAggregateTerminate (self IN OUT AverageImpl, returnValue OUT number, flags IN number)
RETURN number
);
/

ΠΠ°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ контСкста опрСдСляСтся здСсь Π½Π΅ константой, Π° ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎΠΉ (статичСской, Ρ‚ΠΎ Π΅ΡΡ‚ΡŒ Π½Π΅ привязанной ΠΊ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½ΠΎΠΌΡƒ экзСмпляру ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°) Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ ODCIAggregateInitialize.

Ѐункция, вызываСмая для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки β€” это ODCIAggregateIterate.

Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ функция ODCIAggregateTerminate, ΠΈ Π΅ΠΉ, Π·Π°ΠΌΠ΅Ρ‚ΡŒΡ‚Π΅, ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‚ΡΡ Π½Π΅ΠΊΠΈΠ΅ Ρ„Π»Π°Π³ΠΈ, с ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌΠΈ ΠΌΡ‹ разбСрСмся Ρ‡ΡƒΡ‚ΡŒ ΠΏΠΎΠ·ΠΆΠ΅.

Π˜Π½Ρ‚Π΅Ρ€Ρ„Π΅ΠΉΡ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ Π΅Ρ‰Π΅ ΠΎΠ΄Π½Ρƒ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ: ODCIAggregateMerge. ΠœΡ‹ Π΅Π΅ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΠΌ β€” ΠΊΡƒΠ΄Π° ΠΆ Π΄Π΅Π²Π°Ρ‚ΡŒΡΡ, β€” Π½ΠΎ Ρ€Π°Π·Π³ΠΎΠ²ΠΎΡ€ ΠΎ Π½Π΅ΠΉ ΠΏΠΎΠΊΠ° ΠΎΡ‚Π»ΠΎΠΆΠΈΠΌ.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ создадим Ρ‚Π΅Π»ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° с Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠ΅ΠΉ пСрСчислСнных ΠΌΠ΅Ρ‚ΠΎΠ΄ΠΎΠ².

CREATE OR REPLACE TYPE BODY AverageImpl IS
STATIC FUNCTION ODCIAggregateInitialize (actx IN OUT AverageImpl)
RETURN number IS
BEGIN
actx := AverageImpl(0,0);
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateIterate (self IN OUT AverageImpl, val IN number)
RETURN number IS
BEGIN
dbms_output.put_line(self.accum||'(‘||self.qty||’) + ‘||val);
self.accum := self.accum + val;
self.qty := self.qty + 1;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateMerge (self IN OUT AverageImpl, ctx2 IN AverageImpl)
RETURN number IS
BEGIN
dbms_output.put_line(self.accum||'(‘||self.qty||’) & ‘||ctx2.accum||'(‘||ctx2.qty||’)’);
self.accum := self.accum + ctx2.accum;
self.qty := self.qty + ctx2.qty;
RETURN ODCIConst.Success;
END;
MEMBER FUNCTION ODCIAggregateTerminate (self IN OUT AverageImpl, returnValue OUT number, flags IN number)
RETURN number IS
BEGIN
dbms_output.put_line(‘= ‘||self.accum||'(‘||self.qty||’) flags:’||flags);
returnValue := CASE WHEN self.qty > 0 THEN self.accum / self.qty END;
RETURN ODCIConst.Success;
END;
END;
/

РСализация, ΠΏΠΎ большСй части, повторяСт всС Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ ΠΌΡ‹ Π΄Π΅Π»Π°Π»ΠΈ для PostgreSQL, Π½ΠΎ Π² Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ Π΄Ρ€ΡƒΠ³ΠΎΠΌ синтаксисС.

Trim-пляски Π²ΠΎΠΊΡ€ΡƒΠ³ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ значСния Π½Π΅ Π½ΡƒΠΆΠ½Ρ‹: Oracle ΡΠ°ΠΌΠΎΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΎΡ‚Ρ€Π΅Π·Π°Π΅Ρ‚ Π½Π΅Π·Π½Π°Ρ‡Π°Ρ‰ΠΈΠ΅ Π½ΡƒΠ»ΠΈ ΠΏΡ€ΠΈ Π²Ρ‹Π²ΠΎΠ΄Π΅ значСния.

ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ всС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡŽΡ‚ ΠΏΡ€ΠΈΠ·Π½Π°ΠΊ ΡƒΡΠΏΠ΅ΡˆΠ½ΠΎΡΡ‚ΠΈ выполнСния (Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ODCIConst.Success), Π° смысловыС значСния ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‚ΡΡ Ρ‡Π΅Ρ€Π΅Π· ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Ρ‹ OUT ΠΈ IN OUT (ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π² PL/SQL Π½ΠΈΠΊΠ°ΠΊ Π½Π΅ связаны с собствСнно Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΡ‹ΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ, ΠΊΠ°ΠΊ Π² PL/pgSQL). Π’ частности, любая функция, Π² Ρ‚ΠΎΠΌ числС ΠΈ ODCIAggregateTerminate, ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ Π°Ρ‚Ρ€ΠΈΠ±ΡƒΡ‚Ρ‹ своСго ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, ссылка Π½Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ пСрСдаСтся Π΅ΠΉ Π² ΠΏΠ΅Ρ€Π²ΠΎΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€Π΅ (self).

ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

CREATE OR REPLACE FUNCTION average(val number) RETURN number
AGGREGATE USING AverageImpl;
/

ΠŸΡ€ΠΎΠ²Π΅Ρ€ΡΠ΅ΠΌ. Для Π³Π΅Π½Π΅Ρ€Π°Ρ†ΠΈΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ ΠΈΠ΄ΠΈΠΎΠΌΠ°Ρ‚ΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ с рСкурсивным запросом CONNECT BY level:

SELECT average(level) FROM dual CONNECT BY level
МоТно ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚ΡŒ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅ Π½Π° Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π²Ρ‹Π²ΠΎΠ΄ сообщСний Π² PostgreSQL появляСтся Π΄ΠΎ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π°, Π° Π² Oracle β€” послС. Π­Ρ‚ΠΎ ΠΈΠ·-Π·Π° Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎ RAISE NOTICE Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ асинхронно, Π° ΠΏΠ°ΠΊΠ΅Ρ‚ dbms_output Π±ΡƒΡ„Π΅Ρ€ΠΈΠ·ΡƒΠ΅Ρ‚ Π²Ρ‹Π²ΠΎΠ΄.

Как ΠΌΡ‹ Π²ΠΈΠ΄ΠΈΠΌ, Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ODCIAggregateTerminate Π±Ρ‹Π» ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ Π½ΡƒΠ»Π΅Π²ΠΎΠΉ Ρ„Π»Π°Π³. Π­Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ контСкст большС Π½Π΅ трСбуСтся ΠΈ Π΅Π³ΠΎ β€” ΠΏΡ€ΠΈ ΠΆΠ΅Π»Π°Π½ΠΈΠΈ β€” ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π±Ρ‹Ρ‚ΡŒ.

И ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° пустом мноТСствС:

SELECT average(rownum) FROM dual WHERE 1 = 0;
AVERAGE(ROWNUM)
—————

ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ: OVER()

Π₯ΠΎΡ€ΠΎΡˆΠ°Ρ Π½ΠΎΠ²ΠΎΡΡ‚ΡŒ: написанная Π½Π°ΠΌΠΈ агрСгатная функция ΠΌΠΎΠΆΠ΅Ρ‚ Π±Π΅Π· всяких ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ ΠΈ ΠΊΠ°ΠΊ оконная (аналитичСская).

Оконная функция отличаСтся ΠΎΡ‚ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΠΎΠΉ Ρ‚Π΅ΠΌ, Ρ‡Ρ‚ΠΎ Π½Π΅ сворачиваСт Π²Ρ‹Π±ΠΎΡ€ΠΊΡƒ Π² ΠΎΠ΄Π½Ρƒ (Π°Π³Ρ€Π΅Π³ΠΈΡ€ΠΎΠ²Π°Π½Π½ΡƒΡŽ) строку, Π° вычисляСтся ΠΊΠ°ΠΊ Π±Ρ‹ ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки. БинтаксичСски Π²Ρ‹Π·ΠΎΠ² ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ отличаСтся Π½Π°Π»ΠΈΡ‡ΠΈΠ΅ΠΌ конструкции OVER с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ΠΌ Ρ€Π°ΠΌΠΊΠΈ, которая опрСдСляСт мноТСство строк для ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ. Π’ ΠΏΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠ΅ΠΌ случаС ΠΎΠ½Π° Ρ‚Π°ΠΊ ΠΈ записываСтся: OVER(), ΠΈ это ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ функция Π΄ΠΎΠ»ΠΆΠ½Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ всС строки. Π Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ получаСтся Ρ‚Π°ΠΊΠΎΠΉ, ΠΊΠ°ΠΊ Π±ΡƒΠ΄Ρ‚ΠΎ ΠΌΡ‹ посчитали ΠΎΠ±Ρ‹Ρ‡Π½ΡƒΡŽ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΈ записали Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ (ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅) Π½Π°ΠΏΡ€ΠΎΡ‚ΠΈΠ² ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки Π²Ρ‹Π±ΠΎΡ€ΠΊΠΈ.

Π˜Π½Ρ‹ΠΌΠΈ словами, Ρ€Π°ΠΌΠΊΠ° статична ΠΈ ΠΎΡ…Π²Π°Ρ‚Ρ‹Π²Π°Π΅Ρ‚ всС строки:

PostgreSQL

SELECT g.x, average(g.x) OVER ()
FROM generate_series(1,5) as g(x);

NOTICE: 0(0) + 1
NOTICE: 1(1) + 2
NOTICE: 3(2) + 3
NOTICE: 6(3) + 4
NOTICE: 10(4) + 5
NOTICE: = 15(5)
x | average
—+———
1 | 3
2 | 3
3 | 3
4 | 3
5 | 3
(5 rows)

По Π²Ρ‹Π²ΠΎΠ΄Ρƒ NOTICE Π²ΠΈΠ΄Π½ΠΎ, Ρ‡Ρ‚ΠΎ всС происходит Ρ‚ΠΎΡ‡Π½ΠΎ Ρ‚Π°ΠΊ ΠΆΠ΅, ΠΊΠ°ΠΊ ΠΈ Ρ€Π°Π½Π΅Π΅ ΠΏΡ€ΠΈ вычислСнии ΠΎΠ±Ρ‹Ρ‡Π½ΠΎΠΉ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. ΠŸΠΎΠ»ΡƒΡ‡ΠΈΠ² Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΎΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ average_final, PostgreSQL проставляСт Π΅Π³ΠΎ Π² ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строкС.

Oracle

SELECT average(level) OVER() average
FROM dual CONNECT BY level
НСоТиданно. ВмСсто Ρ‚ΠΎΠ³ΠΎ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚ΡŒ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π·, Oracle Π²Ρ‹Π·Ρ‹Π²Π°Π΅Ρ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ODCIAggregateTerminate N+1 Ρ€Π°Π·: сначала для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки с Ρ„Π»Π°Π³ΠΎΠΌ 1 (Ρ‡Ρ‚ΠΎ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ контСкст Π΅Ρ‰Π΅ пригодится) ΠΈ Π·Π°Ρ‚Π΅ΠΌ Π΅Ρ‰Π΅ ΠΎΠ΄ΠΈΠ½ Ρ€Π°Π· Π² ΠΊΠΎΠ½Ρ†Π΅. Π—Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½Π½ΠΎΠ΅ ΠΏΡ€ΠΈ послСднСм Π²Ρ‹Π·ΠΎΠ²Π΅, просто игнорируСтся.

Π’Ρ‹Π²ΠΎΠ΄ Ρ‚Π°ΠΊΠΎΠΉ: Ссли Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ODCIAggregateTerminate ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Π²Ρ‹Ρ‡ΠΈΡΠ»ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ слоТная Π»ΠΎΠ³ΠΈΠΊΠ°, Π½Π°Π΄ΠΎ ΠΏΠΎΠ΄ΡƒΠΌΠ°Ρ‚ΡŒ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π½Π΅ Π΄Π΅Π»Π°Ρ‚ΡŒ ΠΎΠ΄Π½Ρƒ ΠΈ Ρ‚Ρƒ ΠΆΠ΅ Ρ€Π°Π±ΠΎΡ‚Ρƒ нСсколько Ρ€Π°Π·.

ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ: OVER(PARTITION BY)

ΠŸΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ PARTITION BY Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΈ Ρ€Π°ΠΌΠΊΠΈ ΠΏΠΎΡ…ΠΎΠΆΠ΅ Π½Π° ΠΎΠ±Ρ‹Ρ‡Π½ΡƒΡŽ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½ΡƒΡŽ ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ GROUP BY. Оконная функция с ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ΠΌ PARTITION BY вычисляСтся ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½ΠΎ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π³Ρ€ΡƒΠΏΠΏΡ‹ строк, ΠΈ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ приписываСтся ΠΊ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строкС Π²Ρ‹Π±ΠΎΡ€ΠΊΠΈ.

Π’ Ρ‚Π°ΠΊΠΎΠΌ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚Π΅ Ρ€Π°ΠΌΠΊΠ° Ρ‚ΠΎΠΆΠ΅ статична, Π½ΠΎ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π³Ρ€ΡƒΠΏΠΏΡ‹ ΠΎΠ½Π° разная. НапримСр, Ссли ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Ρ‹ Π΄Π²Π΅ Π³Ρ€ΡƒΠΏΠΏΡ‹ строк (с ΠΏΠ΅Ρ€Π²ΠΎΠΉ ΠΏΠΎ Π²Ρ‚ΠΎΡ€ΡƒΡŽ ΠΈ с Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΉ ΠΏΠΎ ΠΏΡΡ‚ΡƒΡŽ), Ρ‚ΠΎ Ρ€Π°ΠΌΠΊΡƒ ΠΌΠΎΠΆΠ½ΠΎ ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ сСбС Ρ‚Π°ΠΊ:

PostgreSQL

SELECT g.x/3 part,
g.x,
average(g.x) OVER (PARTITION BY g.x/3)
FROM generate_series(1,5) as g(x);

NOTICE: 0(0) + 1
NOTICE: 1(1) + 2
NOTICE: = 3(2)
NOTICE: 0(0) + 3
NOTICE: 3(1) + 4
NOTICE: 7(2) + 5
NOTICE: = 12(3)
part | x | average
——+—+———
0 | 1 | 1.5
0 | 2 | 1.5
1 | 3 | 4
1 | 4 | 4
1 | 5 | 4
(5 rows)

ВычислСниС снова происходит ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, Π½ΠΎ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π΅ ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΉ Π³Ρ€ΡƒΠΏΠΏΠ΅ строк состояниС сбрасываСтся Π² Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (initcond).

Oracle

SELECT trunc(level/3) part,
level,
average(level) OVER(PARTITION BY trunc(level/3)) average
FROM dual CONNECT BY level 0(0) + 2
2(1) + 1
= 3(2) flags:1
= 3(2) flags:1
0(0) + 4
4(1) + 5
9(2) + 3
= 12(3) flags:1
= 12(3) flags:1
= 12(3) flags:1
= 12(3) flags:0

Занятно, Ρ‡Ρ‚ΠΎ Oracle Ρ€Π΅ΡˆΠΈΠ» ΠΏΠ΅Ρ€Π΅ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ строки мСстами. Π­Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ Ρ‡Ρ‚ΠΎ-Ρ‚ΠΎ ΡΠΊΠ°Π·Π°Ρ‚ΡŒ ΠΎ дСталях Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ, Π½ΠΎ Π² любом случаС β€” ΠΈΠΌΠ΅Π΅Ρ‚ ΠΏΡ€Π°Π²ΠΎ.

ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ: OVER(ORDER BY)

Если Π² ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ Ρ€Π°ΠΌΠΊΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΏΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ORDER BY, ΡƒΠΊΠ°Π·Ρ‹Π²Π°ΡŽΡ‰Π΅Π΅ порядок сортировки, функция Π½Π°Ρ‡Π½Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ нарастания (для Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ sum ΠΌΡ‹ Π±Ρ‹ Ρ‚Π°ΠΊ ΠΈ сказали β€” Π½Π°Ρ€Π°ΡΡ‚Π°ΡŽΡ‰ΠΈΠΌ ΠΈΡ‚ΠΎΠ³ΠΎΠΌ).

Для ΠΏΠ΅Ρ€Π²ΠΎΠΉ строки Ρ€Π°ΠΌΠΊΠ° Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΡΡ‚ΠΎΡΡ‚ΡŒ ΠΈΠ· ΠΎΠ΄Π½ΠΎΠΉ этой строки; для Π²Ρ‚ΠΎΡ€ΠΎΠΉ β€” ΠΈΠ· ΠΏΠ΅Ρ€Π²ΠΎΠΉ ΠΈ Π²Ρ‚ΠΎΡ€ΠΎΠΉ; для Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΉ β€” ΠΈΠ· ΠΏΠ΅Ρ€Π²ΠΎΠΉ, Π²Ρ‚ΠΎΡ€ΠΎΠΉ ΠΈ Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΉ ΠΈ Ρ‚Π°ΠΊ Π΄Π°Π»Π΅Π΅. Π˜Π½Ρ‹ΠΌΠΈ словами, Π² Ρ€Π°ΠΌΠΊΡƒ Π±ΡƒΠ΄ΡƒΡ‚ Π²Ρ…ΠΎΠ΄ΠΈΡ‚ΡŒ строки с ΠΏΠ΅Ρ€Π²ΠΎΠΉ Π΄ΠΎ Ρ‚Π΅ΠΊΡƒΡ‰Π΅ΠΉ.

На самом Π΄Π΅Π»Π΅, это ΠΌΠΎΠΆΠ½ΠΎ Ρ€ΠΎΠ²Π½ΠΎ Ρ‚Π°ΠΊ ΠΈ Π·Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ: OVER(ORDER BY… ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW), Π½ΠΎ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ это многословиС ΠΏΠΎΠ΄Ρ€Π°Π·ΡƒΠΌΠ΅Π²Π°ΡŽΡ‚ΡΡ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ, Π΅Π³ΠΎ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΎΠΏΡƒΡΠΊΠ°ΡŽΡ‚.

Π˜Ρ‚Π°ΠΊ, Ρ€Π°ΠΌΠΊΠ° пСрСстаСт Π±Ρ‹Ρ‚ΡŒ статичной: Π΅Π΅ Π³ΠΎΠ»ΠΎΠ²Π° двиТСтся Π²Π½ΠΈΠ·, Π° хвост остаСтся Π½Π° мСстС:

PostgreSQL

SELECT g.x, average(g.x) OVER (ORDER BY g.x)
FROM generate_series(1,5) as g(x);

NOTICE: 0(0) + 1
NOTICE: = 1(1)
NOTICE: 1(1) + 2
NOTICE: = 3(2)
NOTICE: 3(2) + 3
NOTICE: = 6(3)
NOTICE: 6(3) + 4
NOTICE: = 10(4)
NOTICE: 10(4) + 5
NOTICE: = 15(5)
x | average
—+———
1 | 1
2 | 1.5
3 | 2
4 | 2.5
5 | 3
(5 rows)

Как Π²ΠΈΠ΄ΠΈΠΌ, строки всС Ρ‚Π°ΠΊ ΠΆΠ΅ Π΄ΠΎΠ±Π°Π²Π»ΡΡŽΡ‚ΡΡ ΠΊ контСксту ΠΏΠΎ ΠΎΠ΄Π½ΠΎΠΉ, Π½ΠΎ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ функция average_final вызываСтся послС ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ добавлСния, выдавая ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹ΠΉ ΠΈΡ‚ΠΎΠ³.

Oracle

SELECT level, average(level) OVER(ORDER BY level) average
FROM dual CONNECT BY level
На этот Ρ€Π°Π· ΠΎΠ±Π΅ систСмы Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‚ ΠΎΠ΄ΠΈΠ½Π°ΠΊΠΎΠ²ΠΎ.

ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ: OVER(PARTITION BY ORDER BY)

ΠŸΡ€Π΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΈΡ PARTITION BY ΠΈ ORDER BY ΠΌΠΎΠΆΠ½ΠΎ ΠΊΠΎΠΌΠ±ΠΈΠ½ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ. Π’ΠΎΠ³Π΄Π° Π²Π½ΡƒΡ‚Ρ€ΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π³Ρ€ΡƒΠΏΠΏΡ‹ строк функция Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ Π² Ρ€Π΅ΠΆΠΈΠΌΠ΅ нарастания, Π° ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄Π΅ ΠΎΡ‚ Π³Ρ€ΡƒΠΏΠΏΡ‹ ΠΊ Π³Ρ€ΡƒΠΏΠΏΠ΅ состояниС Π±ΡƒΠ΄Π΅Ρ‚ ΡΠ±Ρ€Π°ΡΡ‹Π²Π°Ρ‚ΡŒΡΡ Π² Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠ΅.

PostgreSQL

Oracle

ΠžΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ со ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅ΠΉ Ρ€Π°ΠΌΠΊΠΎΠΉ

Π’ΠΎ всСх ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π°Ρ…, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΌΡ‹ посмотрСли, Ρ€Π°ΠΌΠΊΠ° Π»ΠΈΠ±ΠΎ Π±Ρ‹Π»Π° статичСской, Π»ΠΈΠ±ΠΎ двигалась Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Π΅Π΅ Π³ΠΎΠ»ΠΎΠ²Π° (ΠΏΡ€ΠΈ использовании прСдлоТСния ORDER BY). Π­Ρ‚ΠΎ Π΄Π°Π²Π°Π»ΠΎ Π½Π°ΠΌ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΡ‚ΡŒ состояниС ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, добавляя ΠΊ контСксту строку Π·Π° строкой.

Но Ρ€Π°ΠΌΠΊΡƒ ΠΎΠΊΠΎΠ½Π½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ ΠΈ Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π΅Π΅ хвост Ρ‚ΠΎΠΆΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΌΠ΅Ρ‰Π°Ρ‚ΡŒΡΡ. Π’ нашСм ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π΅ это Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΠΎΠ½ΡΡ‚ΠΈΡŽ ΡΠΊΠΎΠ»ΡŒΠ·ΡΡ‰Π΅Π³ΠΎ срСднСго. НапримСр, ΡƒΠΊΠ°Π·Π°Π½ΠΈΠ΅ OVER(ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ для ΠΊΠ°ΠΆΠ΄ΠΎΠΉ строки Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π° Π±ΡƒΠ΄ΡƒΡ‚ ΡƒΡΡ€Π΅Π΄Π½ΡΡ‚ΡŒΡΡ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΈ Π΄Π²Π° ΠΏΡ€Π΅Π΄Ρ‹Π΄ΡƒΡ‰ΠΈΡ… Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ.

Π‘ΠΌΠΎΠΆΠ΅Ρ‚ Π»ΠΈ Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΡ‚ΡŒΡΡ оконная функция Π² Ρ‚Π°ΠΊΠΎΠΌ случаС? ΠžΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ΡΡ, смоТСт, ΠΏΡ€Π°Π²Π΄Π° нСэффСктивно. Но, написав Π΅Ρ‰Π΅ Π½Π΅ΠΌΠ½ΠΎΠ³ΠΎ ΠΊΠΎΠ΄Π°, ΠΌΠΎΠΆΠ½ΠΎ ΡƒΠ»ΡƒΡ‡ΡˆΠΈΡ‚ΡŒ ΡΠΈΡ‚ΡƒΠ°Ρ†ΠΈΡŽ.

PostgreSQL

SELECT g.x,
average(g.x) OVER (ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
FROM generate_series(1,5) as g(x);

NOTICE: 0(0) + 1
NOTICE: = 1(1)
NOTICE: 1(1) + 2
NOTICE: = 3(2)
NOTICE: 3(2) + 3
NOTICE: = 6(3)
NOTICE: 0(0) + 2
NOTICE: 2(1) + 3
NOTICE: 5(2) + 4
NOTICE: = 9(3)
NOTICE: 0(0) + 3
NOTICE: 3(1) + 4
NOTICE: 7(2) + 5
NOTICE: = 12(3)
x | average
—+———
1 | 1
2 | 1.5
3 | 2
4 | 3
5 | 4
(5 rows)

Π’ΠΏΠ»ΠΎΡ‚ΡŒ Π΄ΠΎ Ρ‚Ρ€Π΅Ρ‚ΡŒΠ΅ΠΉ строки всС ΠΈΠ΄Π΅Ρ‚ Ρ…ΠΎΡ€ΠΎΡˆΠΎ, ΠΏΠΎΡ‚ΠΎΠΌΡƒ Ρ‡Ρ‚ΠΎ хвост фактичСски Π½Π΅ двигаСтся: ΠΌΡ‹ просто добавляСм ΠΊ ΡƒΠΆΠ΅ ΠΈΠΌΠ΅ΡŽΡ‰Π΅ΠΌΡƒΡΡ контСксту ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Но, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ Π½Π΅ ΡƒΠΌΠ΅Π΅ΠΌ ΡƒΠ±ΠΈΡ€Π°Ρ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈΠ· контСкста, для Ρ‡Π΅Ρ‚Π²Π΅Ρ€Ρ‚ΠΎΠΉ ΠΈ пятой строк всС приходится ΠΏΠ΅Ρ€Π΅ΡΡ‡ΠΈΡ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ, ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ Ρ€Π°Π· Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΡΡΡŒ ΠΊ Π½Π°Ρ‡Π°Π»ΡŒΠ½ΠΎΠΌΡƒ ΡΠΎΡΡ‚ΠΎΡΠ½ΠΈΡŽ.

Π˜Ρ‚Π°ΠΊ, Π±Ρ‹Π»ΠΎ Π±Ρ‹ Π·Π΄ΠΎΡ€ΠΎΠ²ΠΎ ΠΈΠΌΠ΅Ρ‚ΡŒ Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ добавлСния ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠ³ΠΎ значСния, Π½ΠΎ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ удалСния значСния ΠΈΠ· состояния. И Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ, Ρ‚Π°ΠΊΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΌΠΎΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ:

Π§Ρ‚ΠΎΠ±Ρ‹ оконная функция смогла Π΅ΠΉ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ, Π½ΡƒΠΆΠ½ΠΎ ΠΏΠ΅Ρ€Π΅ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π°Π³Ρ€Π΅Π³Π°Ρ‚ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

Oracle

Π’ΡƒΡ‚ ситуация Π°Π½Π°Π»ΠΎΠ³ΠΈΡ‡Π½Π°. Π‘ΠΎΠ·Π΄Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ аналитичСской Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚, Π½ΠΎ нСэффСктивно:

SELECT level,
average(level) OVER(ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) average
FROM dual CONNECT BY level 0(0) + 2
2(1) + 3
5(2) + 4
= 9(3) flags:1
0(0) + 3
3(1) + 4
7(2) + 5
= 12(3) flags:1
= 12(3) flags:0

Ѐункция удалСния значСния ΠΈΠ· контСкста опрСдСляСтся ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

ΠŸΠ΅Ρ€Π΅ΡΠΎΠ·Π΄Π°Π²Π°Ρ‚ΡŒ саму Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ. ΠŸΡ€ΠΎΠ²Π΅Ρ€ΠΈΠΌ:

ΠŸΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒ

И PostgreSQL, ΠΈ Oracle (Enterprise Edition) ΡƒΠΌΠ΅ΡŽΡ‚ Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΡ‚ΡŒ Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π² ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅. ΠŸΡ€ΠΈ этом ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΈΠ· ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹Ρ… процСссов выполняСт свою Ρ‡Π°ΡΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρ‹, формируя ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½ΠΎΠ΅ состояниС. Π—Π°Ρ‚Π΅ΠΌ основной процСсс-ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½Π°Ρ‚ΠΎΡ€ ΠΏΠΎΠ»ΡƒΡ‡Π°Π΅Ρ‚ эти нСсколько состояний ΠΈ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΠ±ΡŠΠ΅Π΄ΠΈΠ½ΠΈΡ‚ΡŒ ΠΈΡ… Π² ΠΎΠ΄Π½ΠΎ ΠΈΡ‚ΠΎΠ³ΠΎΠ²ΠΎΠ΅.

Для этого Π½ΡƒΠΆΠ½Π° Π΅Ρ‰Π΅ ΠΎΠ΄Π½Π° функция объСдинСния, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΠΌΡ‹ сСйчас ΠΈ напишСм. Π’ нашСм случаС ΠΎΠ½Π° просто складываСт ΠΈ суммы, ΠΈ количСство Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ.

PostgreSQL

Ѐункция выглядит ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ:

ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ ΡƒΠ±ΠΈΡ€Π°Π΅ΠΌ Π²Ρ‹Π²ΠΎΠ΄, Ρ‚ΠΎ ΠΎΡ‚ΠΏΠ°Π΄Π°Π΅Ρ‚ ΠΈ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π½Ρ‹ΠΉ язык β€” напишСм Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ Π½Π° чистом SQL:

CREATE TABLE t(n) AS SELECT generate_series(1,1000)::numeric;

Π‘ настройками ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ PostgreSQL Π½Π΅ построит ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½Ρ‹ΠΉ ΠΏΠ»Π°Π½ для Ρ‚Π°ΠΊΠΎΠΉ Ρ‚Π°Π±Π»ΠΈΡ†Ρ‹ β€” слишком ΠΎΠ½Π° ΠΌΠ°Π»Π°, β€” Π½ΠΎ Π΅Π³ΠΎ нСслоТно ΡƒΠ³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ΡŒ:

SET parallel_setup_cost=0;
SET min_parallel_table_scan_size=0;

EXPLAIN(costs off) SELECT average(n) FROM t;
QUERY PLAN
——————————————
Finalize Aggregate
-> Gather
Workers Planned: 2
-> Partial Aggregate
-> Parallel Seq Scan on t

Π’ ΠΏΠ»Π°Π½Π΅ запроса Π²ΠΈΠ΄ΠΈΠΌ:

SELECT average(n) FROM t;
NOTICE: 0(0) & 281257(678)
NOTICE: 281257(678) & 127803(226)
NOTICE: 409060(904) & 91440(96)
NOTICE: = 500500(1000)
average
———
500.5
(1 row)

ΠŸΠΎΡ‡Π΅ΠΌΡƒ функция average_combine вызываСтся Ρ‚Ρ€ΠΈ Ρ€Π°Π·Π°, Π° Π½Π΅ Π΄Π²Π°? Π”Π΅Π»ΠΎ Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π² PostgreSQL ΠΊΠΎΠΎΡ€Π΄ΠΈΠ½ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ процСсс Ρ‚ΠΎΠΆΠ΅ выполняСт Ρ‡Π°ΡΡ‚ΡŒ Ρ€Π°Π±ΠΎΡ‚Ρ‹. ΠŸΠΎΡΡ‚ΠΎΠΌΡƒ, хотя Π±Ρ‹Π»ΠΎ Π·Π°ΠΏΡƒΡ‰Π΅Π½ΠΎ Π΄Π²Π° Ρ€Π°Π±ΠΎΡ‡ΠΈΡ… процСсса, Ρ€Π΅Π°Π»ΡŒΠ½ΠΎ Ρ€Π°Π±ΠΎΡ‚Π° Π²Ρ‹ΠΏΠΎΠ»Π½ΡΠ»Π°ΡΡŒ Π² Ρ‚Ρ€Π΅Ρ…. Один ΠΈΠ· Π½ΠΈΡ… успСл ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ 678 строк, Π΄Ρ€ΡƒΠ³ΠΎΠΉ 226 ΠΈ Ρ‚Ρ€Π΅Ρ‚ΠΈΠΉ β€” 96 (хотя эти Ρ†ΠΈΡ„Ρ€Ρ‹ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ Π·Π½Π°Ρ‡Π°Ρ‚ ΠΈ ΠΏΡ€ΠΈ Π΄Ρ€ΡƒΠ³ΠΎΠΌ запускС ΠΌΠΎΠ³ΡƒΡ‚ ΠΎΡ‚Π»ΠΈΡ‡Π°Ρ‚ΡŒΡΡ).

Oracle

Если ΠΏΠΎΠΌΠ½ΠΈΡ‚Π΅, Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ODCIAggregateMerge ΠΌΡ‹ ΡƒΠΆΠ΅ написали Π² самом Π½Π°Ρ‡Π°Π»Π΅, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π² Oracle ΠΎΠ½Π° являСтся ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠΉ. ДокумСнтация настаиваСт, Ρ‡Ρ‚ΠΎ эта функция Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠ° Π½Π΅ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ для ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹, Π½ΠΎ ΠΈ для ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠΉ β€” хотя ΠΌΠ½Π΅ Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ ΠΏΠΎΠ½ΡΡ‚ΡŒ, Π·Π°Ρ‡Π΅ΠΌ (ΠΈ Π½Π° ΠΏΡ€Π°ΠΊΡ‚ΠΈΠΊΠ΅ Π½Π΅ ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΠ»ΠΎΡΡŒ ΡΡ‚Π°Π»ΠΊΠΈΠ²Π°Ρ‚ΡŒΡΡ с Π΅Π΅ Π²Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ΠΌ ΠΏΡ€ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠΉ ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ΅).

ВсС, Ρ‡Ρ‚ΠΎ остаСтся ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ β€” ΠΎΠ±ΡŠΡΠ²ΠΈΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ бСзопасной для ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹:

CREATE OR REPLACE FUNCTION average(val number) RETURN number
PARALLEL_ENABLE
AGGREGATE USING AverageImpl;
/

Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ Ρ‚Π°Π±Π»ΠΈΡ†Ρƒ:

CREATE TABLE t(n) AS SELECT to_number(level) FROM dual CONNECT BY level
Π£Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ΡŒ Oracle Π΅Ρ‰Π΅ ΠΏΡ€ΠΎΡ‰Π΅, Ρ‡Π΅ΠΌ PostgreSQL β€” достаточно Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Ρ…ΠΈΠ½Ρ‚. Π’ΠΎΡ‚ ΠΊΠ°ΠΊΠΎΠΉ получаСтся ΠΏΠ»Π°Π½ (Π²Ρ‹Π²ΠΎΠ΄ сильно ΡƒΡ€Π΅Π·Π°Π½ для простоты):

EXPLAIN PLAN FOR SELECT /*+ PARALLEL(2) */ average(n) FROM t;
SELECT * FROM TABLE(dbms_xplan.display);

———————————
| Id | Operation |
———————————
| 0 | SELECT STATEMENT |
| 1 | SORT AGGREGATE |
| 2 | PX COORDINATOR |
| 3 | PX SEND QC (RANDOM) |
| 4 | SORT AGGREGATE |
| 5 | PX BLOCK ITERATOR |
| 6 | TABLE ACCESS FULL |
———————————

План Ρ‚Π°ΠΊΠΆΠ΅ содСрТит:

ДокумСнтация

Π‘Π°ΠΌΠΎΠ΅ врСмя привСсти ссылки Π½Π° Π΄ΠΎΠΊΡƒΠΌΠ΅Π½Ρ‚Π°Ρ†ΠΈΡŽ, Π² Ρ‚ΠΎΠΌ числС ΠΈ Π½Π° Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Π΅ ΠΈ ΠΎΠΊΠΎΠ½Π½Ρ‹Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ, ΡƒΠΆΠ΅ Π²ΠΊΠ»ΡŽΡ‡Π΅Π½Π½Ρ‹ΠΌ Π² Π‘Π£Π‘Π”. Π’Π°ΠΌ ΠΌΠΎΠΆΠ½ΠΎ Π½Π°ΠΉΡ‚ΠΈ ΠΌΠ½ΠΎΠ³ΠΎ интСрСсного.

ΠŸΡ€ΠΈΠΌΠ΅Ρ€ ΠΏΡ€ΠΎ ΠΎΠΊΡ€ΡƒΠ³Π»Π΅Π½ΠΈΠ΅ ΠΊΠΎΠΏΠ΅Π΅ΠΊ

И ΠΎΠ±Π΅Ρ‰Π°Π½Π½Ρ‹ΠΉ ΠΏΡ€ΠΈΠΌΠ΅Ρ€ ΠΈΠ· ΠΆΠΈΠ·Π½ΠΈ. Π­Ρ‚Ρƒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ я ΠΏΡ€ΠΈΠ΄ΡƒΠΌΠ°Π», ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΈΡ…ΠΎΠ΄ΠΈΠ»ΠΎΡΡŒ ΠΏΠΈΡΠ°Ρ‚ΡŒ ΠΎΡ‚Ρ‡Π΅Ρ‚Ρ‹ для Π±ΡƒΡ…Π³Π°Π»Ρ‚Π΅Ρ€ΠΈΠΈ, Ρ€Π°Π±ΠΎΡ‚Π°ΡŽΡ‰Π΅ΠΉ ΠΏΠΎ Π Π‘Π‘Π£ (ΠΏΡ€Π°Π²ΠΈΠ»Π°ΠΌ российского Π±ΡƒΡ…ΡƒΡ‡Π΅Ρ‚Π°).

Бамая простая Π·Π°Π΄Π°Ρ‡Π°, Π² ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΉ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎΡΡ‚ΡŒ округлСния β€” распрСдСлСниС ΠΎΠ±Ρ‰ΠΈΡ… расходов (скаТСм, 100 Ρ€ΡƒΠ±Π»Π΅ΠΉ) Π½Π° ΠΎΡ‚Π΄Π΅Π»Ρ‹ (скаТСм, 3 ΡˆΡ‚ΡƒΠΊΠΈ) ΠΏΠΎ ΠΊΠ°ΠΊΠΎΠΌΡƒ-Ρ‚ΠΎ ΠΏΡ€ΠΈΠ½Ρ†ΠΈΠΏΡƒ (скаТСм, ΠΏΠΎΡ€ΠΎΠ²Π½Ρƒ):

WITH depts(name) AS (
VALUES (‘A’), (‘B’), (‘C’)
), report(dept,amount) AS (
SELECT name, 100.00 / count(*) OVER() FROM depts
)
SELECT dept, round(amount,2) FROM report;

dept | round
——+——-
A | 33.33
B | 33.33
C | 33.33
(3 rows)

Π­Ρ‚ΠΎΡ‚ запрос ΠΏΠΎΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡƒ: суммы Π½Π°Π΄ΠΎ ΠΎΠΊΡ€ΡƒΠ³Π»ΡΡ‚ΡŒ, Π½ΠΎ ΠΏΡ€ΠΈ этом тСряСтся ΠΊΠΎΠΏΠ΅ΠΉΠΊΠ°. А Π Π‘Π‘Π£ этого Π½Π΅ ΠΏΡ€ΠΎΡ‰Π°Π΅Ρ‚.

Π—Π°Π΄Π°Ρ‡Ρƒ ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π΅ΡˆΠ°Ρ‚ΡŒ ΠΏΠΎ-Ρ€Π°Π·Π½ΠΎΠΌΡƒ, Π½ΠΎ Π½Π° ΠΌΠΎΠΉ вкус Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ элСгантный способ β€” оконная функция, которая Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ Π² Π½Π°Ρ€Π°ΡΡ‚Π°ΡŽΡ‰Π΅ΠΌ Ρ€Π΅ΠΆΠΈΠΌΠ΅ ΠΈ Π±Π΅Ρ€Π΅Ρ‚ всю Π±ΠΎΡ€ΡŒΠ±Ρƒ с ΠΊΠΎΠΏΠ΅ΠΉΠΊΠ°ΠΌΠΈ Π½Π° сСбя:

WITH depts(name) AS (
VALUES (‘A’), (‘B’), (‘C’)
), report(dept,amount) AS (
SELECT name, 100.00 / count(*) OVER() FROM depts
)
SELECT dept, round2(amount) OVER (ORDER BY dept) FROM report;

dept | round2
——+———
A | 33.33
B | 33.34
C | 33.33
(3 rows)

БостояниС Ρ‚Π°ΠΊΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π²ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ округлСния (r_error) ΠΈ Ρ‚Π΅ΠΊΡƒΡ‰Π΅Π΅ ΠΎΠΊΡ€ΡƒΠ³Π»Π΅Π½Π½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ (amount). Ѐункция ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ΠΎΡ‡Π΅Ρ€Π΅Π΄Π½ΠΎΠ³ΠΎ значСния ΡƒΠ²Π΅Π»ΠΈΡ‡ΠΈΠ²Π°Π΅Ρ‚ ΠΎΡˆΠΈΠ±ΠΊΡƒ округлСния, ΠΈ, Ссли ΠΎΠ½Π° ΡƒΠΆΠ΅ ΠΏΡ€Π΅Π²Ρ‹ΡˆΠ°Π΅Ρ‚ ΠΏΠΎΠ»ΠΊΠΎΠΏΠ΅ΠΉΠΊΠΈ, добавляСт ΠΊ ΠΎΠΊΡ€ΡƒΠ³Π»Π΅Π½Π½ΠΎΠΉ суммС ΠΊΠΎΠΏΠ΅Π΅Ρ‡ΠΊΡƒ:

ΠŸΠΎΠ»Π½Ρ‹ΠΉ ΠΊΠΎΠ΄ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ΡŒ Π½Π΅ Π±ΡƒΠ΄Ρƒ: ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ ΡƒΠΆΠ΅ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹Π΅ ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ Π½Π°ΠΏΠΈΡΠ°Ρ‚ΡŒ Π΅Π΅ Π½Π΅ прСдставляСт слоТности.

Если Π²Π°ΠΌ Π²ΡΡ‚Ρ€Π΅Ρ‡Π°Π»ΠΈΡΡŒ интСрСсныС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Ρ‹ использования собствСнных Π°Π³Ρ€Π΅Π³Π°Ρ‚Π½Ρ‹Ρ… ΠΈΠ»ΠΈ ΠΎΠΊΠΎΠ½Π½Ρ‹Ρ… Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ β€” ΠΏΠΎΠ΄Π΅Π»ΠΈΡ‚Π΅ΡΡŒ ΠΈΠΌΠΈ Π² коммСнтариях.

Π˜ΡΡ‚ΠΎΡ‡Π½ΠΈΠΊ

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

Π’Π°Ρˆ адрСс email Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½. ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ поля ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Ρ‹ *