{"id":373834,"date":"2024-05-21T05:45:29","date_gmt":"2024-05-21T05:45:29","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=373834"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=373834","title":{"rendered":"<span>\u00abIT-\u041f\u043b\u0430\u043d\u0435\u0442\u0430 2024\u00bb: \u0437\u0430\u0434\u0430\u0447\u0438 \u0432\u0442\u043e\u0440\u043e\u0433\u043e \u044d\u0442\u0430\u043f\u0430 \u043f\u043e PostgreSQL<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0432\u0448\u0438\u0441\u044c \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e\u0434\u043d\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c, \u043c\u044b <a href=\"https:\/\/habr.com\/ru\/companies\/postgrespro\/articles\/742684\/\">\u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043b\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u043d\u0438\u0435<\/a> \u0438 \u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043c \u043a\u043e\u043d\u043a\u0443\u0440\u0441 \u043f\u043e SQL \u043d\u0430 \u043c\u0435\u0436\u0434\u0443\u043d\u0430\u0440\u043e\u0434\u043d\u043e\u0439 \u043e\u043b\u0438\u043c\u043f\u0438\u0430\u0434\u0435 \u00ab<a href=\"https:\/\/world-it-planet.org\/\">IT-\u041f\u043b\u0430\u043d\u0435\u0442\u0430<\/a>\u00bb.<\/p>\n<p>\u041a\u043e\u043d\u043a\u0443\u0440\u0441 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0435\u0445 \u044d\u0442\u0430\u043f\u043e\u0432. \u0417\u0430\u043e\u0447\u043d\u044b\u0439 \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0435\u0441\u0442 \u0441\u043e\u0431\u0440\u0430\u043b \u043f\u043e\u0447\u0442\u0438 3000 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u0430\u043f \u043c\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 200. \u0412\u043e\u043f\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044d\u0442\u0430\u043f\u0430 \u0431\u044b\u043b\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u044b \u043c\u043e\u0438\u043c \u043a\u043e\u043b\u043b\u0435\u0433\u043e\u0439, \u0415\u0432\u0433\u0435\u043d\u0438\u0435\u043c \u0414\u0430\u0432\u044b\u0434\u043e\u0432\u044b\u043c.<\/p>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u044d\u0442\u0430\u043f \u2014 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043e\u0447\u043d\u044b\u0439. \u0417\u0434\u0435\u0441\u044c \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430\u043c \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043e \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u043d\u0430\u0434 \u043f\u044f\u0442\u044c\u044e \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u043c\u043e\u0435\u0433\u043e \u0430\u0432\u0442\u043e\u0440\u0441\u0442\u0432\u0430, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044f \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0438 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c.<\/p>\n<p>\u0422\u0440\u0435\u0442\u0438\u0439 \u2014 \u043e\u0447\u043d\u044b\u0439 \u2014 \u044d\u0442\u0430\u043f \u043f\u0440\u043e\u0439\u0434\u0435\u0442 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043c\u0430\u044f; \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043d\u0435 \u0437\u0430\u0442\u044f\u0433\u0438\u0432\u0430\u0442\u044c \u0441 \u043e\u0442\u0447\u0435\u0442\u043e\u043c, \u043d\u043e \u043f\u043e\u043a\u0430 \u0445\u0440\u0430\u043d\u044e \u0438\u043d\u0442\u0440\u0438\u0433\u0443\u044e\u0449\u0435\u0435 \u043c\u043e\u043b\u0447\u0430\u043d\u0438\u0435.<\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432\u0441\u0435 \u0432\u0432\u043e\u0434\u043d\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u043f\u0440\u043e \u043c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u044e \u044f \u0443\u0436\u0435 \u0441\u043a\u0430\u0437\u0430\u043b \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437, \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0434\u0435\u043b\u0443.<\/p>\n<h2>\u0417\u0430\u0434\u0430\u0447\u0430 1. \u041c\u043d\u043e\u0433\u043e\u0433\u043e\u043b\u043e\u0432\u044b\u0439 \u0426\u0435\u0440\u0431\u0435\u0440<\/h2>\n<h3>\u0423\u0441\u043b\u043e\u0432\u0438\u0435<\/h3>\n<p>\u0412\u0445\u043e\u0434 \u0432 \u043f\u043e\u0434\u0437\u0435\u043c\u0435\u043b\u044c\u0435 \u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043c\u043d\u043e\u0433\u043e\u0433\u043e\u043b\u043e\u0432\u044b\u0438\u0306 \u043f\u0435\u0441. \u041c\u0443\u0437\u044b\u043a\u0430 \u043d\u0430 \u043d\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u0438\u0306\u0441\u0442\u0432\u0443\u0435\u0442, \u043d\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u0433\u043e\u043b\u043e\u0432 \u043e\u0442\u0434\u044b\u0445\u0430\u044e\u0442. \u0413\u0430\u0440\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b \u043d\u0430 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u043c \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0432\u0438\u0434\u0435\u043e\u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0433\u043e\u043b\u043e\u0432. \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u043d\u0430\u0434\u0435\u0436\u043d\u043e \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u0441\u044b\u043f\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0441\u044b\u043f\u0430\u043d\u0438\u044f \u0433\u043e\u043b\u043e\u0432, \u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b. <\/p>\n<p>\u0418\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0442\u043e \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432\u0441\u0435 \u0433\u043e\u043b\u043e\u0432\u044b \u0431\u043e\u0434\u0440\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0438, \u0430 \u0437\u0430 \u043f\u0435\u0440\u0438\u043e\u0434 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u0430\u044f \u0438\u0437 \u0433\u043e\u043b\u043e\u0432 \u0437\u0430\u0441\u044b\u043f\u0430\u043b\u0430 \u0445\u043e\u0442\u044f \u0431\u044b \u0440\u0430\u0437. <\/p>\n<p>\u0412\u044b\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0413\u0430\u0440\u0440\u0438 \u0438 \u0435\u0433\u043e \u0434\u0440\u0443\u0437\u044c\u044f \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043f\u0440\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u043c\u0438\u043c\u043e \u043f\u0441\u0430. <\/p>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 cerberus: <\/p>\n<pre><code class=\"pgsql\">CREATE TABLE cerberus(   head_id integer NOT NULL,      -- \u043d\u043e\u043c\u0435\u0440 \u0433\u043e\u043b\u043e\u0432\u044b   event_time timestamp NOT NULL, -- \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f   head_state boolean NOT NULL,   -- true - \u0431\u043e\u0434\u0440\u0441\u0442\u0432\u0443\u0435\u0442, false - \u0441\u043f\u0438\u0442   UNIQUE (head_id, event_time) );<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b (\u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f), \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0435 \u0433\u043e\u043b\u043e\u0432\u044b \u0441\u043f\u0430\u043b\u0438. <\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 <\/h4>\n<p>\u0414\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 <\/p>\n<pre><code class=\"pgsql\">INSERT INTO cerberus VALUES   (1, '2024-04-01 01:00:00'::timestamp, false), -- 1-\u044f \u0443\u0441\u043d\u0443\u043b\u0430   (3, '2024-04-01 02:00:00'::timestamp, false), -- 3-\u044f \u0443\u0441\u043d\u0443\u043b\u0430   (2, '2024-04-01 03:00:00'::timestamp, false), -- 2-\u044f \u0443\u0441\u043d\u0443\u043b\u0430   (2, '2024-04-01 04:00:00'::timestamp, true),  -- 2-\u044f \u043f\u0440\u043e\u0441\u043d\u0443\u043b\u0430\u0441\u044c   (1, '2024-04-01 04:30:00'::timestamp, false), -- 1-\u044f \u0441\u043f\u0438\u0442   (1, '2024-04-01 05:00:00'::timestamp, true),  -- 1-\u044f \u043f\u0440\u043e\u0441\u043d\u0443\u043b\u0430\u0441\u044c   (3, '2024-04-01 06:00:00'::timestamp, true);  -- 3-\u044f \u043f\u0440\u043e\u0441\u043d\u0443\u043b\u0430\u0441\u044c <\/code><\/pre>\n<p>\u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438: <\/p>\n<pre><code>      time_from      |       time_to ---------------------+---------------------  2024-04-01 03:00:00 | 2024-04-01 04:00:00 (1 rows) <\/code><\/pre>\n<p>(\u0412 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u044f \u043d\u0435 \u0432\u043f\u043e\u043b\u043d\u0435 \u0447\u0435\u0442\u043a\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b, \u0447\u0442\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441, \u0435\u0441\u043b\u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f \u0432\u0441\u0435 \u0433\u043e\u043b\u043e\u0432\u044b \u0441\u043f\u044f\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b \u043b\u044e\u0431\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442.)<\/p>\n<h3>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0432\u0438\u0434\u0435\u043b\u0430\u0441\u044c \u043c\u043d\u0435 \u043a\u0430\u043a \u0430\u043f\u0435\u0440\u0438\u0442\u0438\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0438\u043d\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u0431\u043b\u044e\u0434\u043e\u043c, \u043d\u043e \u0441\u043e \u0441\u0432\u043e\u0435\u0439 \u0438\u0437\u044e\u043c\u0438\u043d\u043a\u043e\u0439. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u0435\u0448\u0430\u0442\u044c \u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u0438 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e PostgreSQL \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430\u043c\u0438, \u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 14-\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u2014 \u0438 \u0441 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430\u043c\u0438, \u0436\u0438\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0432\u0435\u0441\u0435\u043b\u0435\u0435 \u0438 \u043f\u0440\u043e\u0449\u0435.<\/p>\n<p>\u0412\u0441\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u043e\u043b\u043e\u0432\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b \u0441\u043d\u0430 \u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u0445 \u0432 \u043e\u0434\u0438\u043d \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d, \u0430 \u0437\u0430\u0442\u0435\u043c \u043d\u0430\u0439\u0442\u0438 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432 \u0432\u0441\u0435\u0445 \u0433\u043e\u043b\u043e\u0432.<\/p>\n<p>\u0414\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b \u0441\u043d\u0430 \u043b\u0435\u0433\u043a\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u043a\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>lead<\/code>: \u0431\u0435\u0440\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043e\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0437\u0430\u0441\u044b\u043f\u0430\u043d\u0438\u044f \u0434\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0437\u0430 \u043d\u0438\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u0427\u0442\u043e \u043f\u0440\u0438\u044f\u0442\u043d\u043e, \u043d\u0430\u043c \u043d\u0435 \u0432\u0430\u0436\u043d\u043e, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043b\u0438 \u0437\u0430 \u0437\u0430\u0441\u044b\u043f\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0431\u0443\u0436\u0434\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043d\u0430: \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043c\u044b\u043a\u0430\u044e\u0449\u0438\u0445 \u0434\u0440\u0443\u0433 \u043a \u0434\u0440\u0443\u0433\u0443 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432, \u044d\u0442\u043e \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442.<\/p>\n<p>\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432 \u0432 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0438 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u043c\u0443\u043b\u044c\u0442\u0438\u0437\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 <code>range_agg<\/code> \u0438 <code>range_intersect_agg<\/code>, \u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u0441\u043d\u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b \u043c\u043e\u0436\u043d\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>unnest<\/code>. \u0412\u0441\u044e \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0438 \u0441\u043a\u0443\u0447\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 PostgreSQL \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0437\u0430 \u043d\u0430\u0441.<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"pgsql\">WITH ranges AS (   -- \u041e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u043f\u043e\u0434\u0440\u044f\u0434 \u0438\u0434\u0443\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 (\u043d\u0430\u0447\u0438\u043d\u0430\u044f \u043e\u0442 \u0437\u0430\u0441\u044b\u043f\u0430\u043d\u0438\u044f) \u0432 \u043e\u0434\u0438\u043d \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d.   -- \u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0430\u043c \u043d\u0435 \u043c\u0435\u0448\u0430\u044e\u0442: \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0430\u043b\u044c\u0448\u0435   -- \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0441\u043e\u043b\u044c\u044e\u0442\u0441\u044f \u0432 \u043e\u0434\u0438\u043d \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d.   SELECT head_id, tsrange(event_time, next_time) off_range   FROM (     SELECT head_id, event_time, head_state,       lead(event_time) OVER (PARTITION BY head_id ORDER BY event_time) next_time     FROM cerberus   ) t      WHERE NOT head_state ), multiranges AS (   -- \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u043c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u043e\u043b\u043e\u0432\u044b \u0432 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d   SELECT range_agg(off_range) off_multirange   FROM ranges   GROUP BY head_id ), intersections AS (   -- \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432   SELECT unnest(range_intersect_agg(off_multirange)) off_range   FROM multiranges ) -- \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0432 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0439 \u043f\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044e \u0432\u0438\u0434 SELECT lower(off_range), upper(off_range) FROM intersections;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a, \u041b\u0435\u043e\u043d\u0438\u0434 \u0410\u043b\u0435\u043a\u0441\u0435\u0435\u0432. \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0440\u0430\u0441\u0447\u0435\u0445\u043b\u044f\u0442\u044c \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0438 \u0434\u0430\u0436\u0435 json-\u044b.<\/p>\n<h4>\u0420\u0443\u0431\u0440\u0438\u043a\u0430 \u00ab\u041d\u0435 \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0442\u0430\u043a\u00bb<\/h4>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 <code>NULL<\/code>, \u043d\u0435 \u043d\u0430\u0434\u043e \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u0438\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 <code>case when cnt.sleepHeadCnt = cnt.totalHeads then true else false end<\/code>. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c <code>cnt.sleepHeadCnt = cnt.totalHeads<\/code>. (\u0410 \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0435\u0442, \u043b\u0443\u0447\u0448\u0435 \u0443\u0436 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0444\u0430\u043a\u0442 \u0431\u043e\u043b\u0435\u0435 \u044f\u0432\u043d\u044b\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <code>coalesce<\/code>.)<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0432\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433 \u0432 \u0434\u0440\u0443\u0433\u0430 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 <code>WITH<\/code>. \u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u0449\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043d\u0430\u0434 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043a\u0430\u043a \u0440\u0430\u0437 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u044f \u0447\u0442\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043b\u0438 \u0437\u0430\u0433\u043b\u0430\u0432\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u2014 \u0434\u0435\u043b\u043e \u0432\u043a\u0443\u0441\u0430, \u043d\u043e \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430\u0431\u0438\u0440\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0431\u0443\u043a\u0432\u0430\u043c\u0438 \u0432\u0435\u0441\u044c \u0437\u0430\u043f\u0440\u043e\u0441. \u0412\u0441\u0435-\u0442\u0430\u043a\u0438 \u0434\u0432\u0430\u0434\u0446\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0435\u043a \u043d\u0430 \u0434\u0432\u043e\u0440\u0435, \u0432\u043e\u0441\u044c\u043c\u0438\u0431\u0438\u0442\u043d\u044b\u0435 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u0437\u0430\u0432\u0435\u0437\u043b\u0438.<\/p>\n<\/li>\n<\/ul>\n<h2>\u0417\u0430\u0434\u0430\u0447\u0430 2. \u0412\u043e\u043b\u0448\u0435\u0431\u043d\u0430\u044f \u043f\u0430\u043b\u043e\u0447\u043a\u0430<\/h2>\n<h3>\u0423\u0441\u043b\u043e\u0432\u0438\u0435<\/h3>\n<p>\u041a\u043e\u0433\u0434\u0430 \u041d\u0435\u0437\u043d\u0430\u0438\u0306\u043a\u0430 \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u0442 \u043f\u044f\u0442\u044c \u0434\u043e\u0431\u0440\u044b\u0445 \u0434\u0435\u043b \u043f\u043e\u0434\u0440\u044f\u0434, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u0438\u043a \u0438 \u0432\u0440\u0443\u0447\u0438\u0442 \u0435\u043c\u0443 \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u0443\u044e \u043f\u0430\u043b\u043e\u0447\u043a\u0443. <\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u041d\u0435\u0437\u043d\u0430\u0438\u0306\u043a\u0430 \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u0442 \u043f\u044f\u0442\u044c \u043f\u043b\u043e\u0445\u0438\u0445 \u0434\u0435\u043b \u043f\u043e\u0434\u0440\u044f\u0434, \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u0438\u043a \u043e\u0442\u0431\u0435\u0440\u0435\u0442 \u0443 \u043d\u0435\u0433\u043e \u043f\u0430\u043b\u043e\u0447\u043a\u0443. <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0430\u043b\u043e\u0447\u043a\u0443 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0438\u0306 \u0440\u0430\u0437, \u041d\u0435\u0437\u043d\u0430\u0438\u0306\u043a\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043d\u0430 \u043e\u0434\u043d\u043e \u0434\u043e\u0431\u0440\u043e\u0435 \u0434\u0435\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0438\u0306 (\u043d\u043e \u0447\u0442\u043e\u0431\u044b \u043b\u0438\u0448\u0438\u0442\u044c\u0441\u044f \u043f\u0430\u043b\u043e\u0447\u043a\u0438, \u0432\u0441\u0435\u0433\u0434\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u044f\u0442\u0438 \u043f\u043b\u043e\u0445\u0438\u0445 \u0434\u0435\u043b \u2014 \u0442\u0430\u043a\u0430\u044f \u043d\u0435\u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0441\u0442\u044c). <\/p>\n<p>\u041d\u0435\u0437\u043d\u0430\u0438\u0306\u043a\u0438\u043d\u044b \u0434\u0435\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 deeds: <\/p>\n<pre><code class=\"pgsql\">CREATE TABLE deeds(   ts timestamp PRIMARY KEY,   good boolean NOT NULL -- t - \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0434\u0435\u043b\u043e, f - \u043f\u043b\u043e\u0445\u043e\u0435 );<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b (<code>tsrange<\/code>) \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u044f \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u043e\u0438\u0306 \u043f\u0430\u043b\u043e\u0447\u043a\u043e\u0438\u0306. <\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 <\/strong><\/p>\n<p>\u0414\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 <\/p>\n<pre><code class=\"pgsql\">INSERT INTO deeds VALUES   ('2024-04-01 01:00:00'::timestamp, true),   ('2024-04-01 02:00:00'::timestamp, true),   ('2024-04-01 03:00:00'::timestamp, false),   ('2024-04-01 04:00:00'::timestamp, true),   ('2024-04-01 05:00:00'::timestamp, true),   ('2024-04-01 06:00:00'::timestamp, true),   ('2024-04-01 07:00:00'::timestamp, true),   ('2024-04-01 08:00:00'::timestamp, true),   ('2024-04-01 09:00:00'::timestamp, false);<\/code><\/pre>\n<p>\u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438: <\/p>\n<pre><code>         range ------------------------  [2024-04-01 08:00:00,) (1 rows)<\/code><\/pre>\n<h3>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0415\u0449\u0435 \u043e\u0434\u043d\u0430 \u0440\u0430\u0437\u043c\u0438\u043d\u043e\u0447\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0430 \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u0435 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u043c\u0438 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438.<\/p>\n<p>\u0414\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u043e-\u043d\u0430\u043f\u0435\u0440\u0432\u043e \u043d\u0430\u0434\u043e \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0432\u0441\u0435 \u0434\u0435\u043b\u0430 \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u044b <em>\u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u043f\u043e\u0434\u0440\u044f\u0434 \u0438\u0434\u0443\u0449\u0438\u0445<\/em>. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"pgsql\">WITH prev AS ( -- \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u0434\u0435\u043b\u043e   SELECT ts, good, lag(good) OVER (ORDER BY ts) prev_good    FROM deeds ), changes AS ( -- \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u044b \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432 \u0434\u0440\u0443\u0433\u043e\u0435   SELECT ts, good, prev_good, CASE WHEN good != prev_good THEN 1 END change   FROM prev ) -- \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u043d\u0430\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0438\u043c \u0438\u0442\u043e\u0433\u043e\u043c \u0434\u0430\u0435\u0442 \u043d\u043e\u043c\u0435\u0440\u0430 \u0433\u0440\u0443\u043f\u043f SELECT ts, good, prev_good, change, count( change ) OVER (ORDER BY ts) grp  FROM changes ORDER BY ts;<\/code><\/pre>\n<pre><code>         ts          | good | prev_good | change | grp  ---------------------+------+-----------+--------+-----  2024-04-01 01:00:00 | t    |           |        |   0  2024-04-01 02:00:00 | t    | t         |        |   0  2024-04-01 03:00:00 | f    | t         |      1 |   1  2024-04-01 04:00:00 | t    | f         |      1 |   2  2024-04-01 05:00:00 | t    | t         |        |   2  2024-04-01 06:00:00 | t    | t         |        |   2  2024-04-01 07:00:00 | t    | t         |        |   2  2024-04-01 08:00:00 | t    | t         |        |   2  2024-04-01 09:00:00 | f    | t         |      1 |   3 (9 rows)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0430\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0438\u043c \u0438\u0442\u043e\u0433\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0435\u043b \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435: \u0443\u0434\u043e\u0431\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0438\u0435 \u0434\u0435\u043b\u0430 \u0441 \u043f\u043b\u044e\u0441\u043e\u043c, \u0430 \u043f\u043b\u043e\u0445\u0438\u0435 \u2014 \u0441 \u043c\u0438\u043d\u0443\u0441\u043e\u043c.<\/p>\n<pre><code class=\"pgsql\">WITH grps AS (   -- \u044d\u0442\u043e \u043c\u044b \u0443\u0436\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u0432\u044b\u0448\u0435, \u043d\u043e \u0442\u0443\u0442 +1\/-1 \u0432\u043c\u0435\u0441\u0442\u043e boolean   SELECT ts,      CASE WHEN good THEN 1 ELSE -1 END grade,      count( change ) OVER (ORDER BY ts) grp    FROM (     SELECT ts, good,        CASE WHEN good != lag(good) OVER (ORDER BY ts) THEN 1 END change      FROM deeds   ) ) SELECT ts, grade, grp, sum(grade) OVER (PARTITION BY grp ORDER BY ts)  FROM grps ORDER BY ts; <\/code><\/pre>\n<pre><code>         ts          | grade | grp | sum  ---------------------+-------+-----+-----  2024-04-01 01:00:00 |     1 |   0 |   1  2024-04-01 02:00:00 |     1 |   0 |   2  2024-04-01 03:00:00 |    -1 |   1 |  -1  2024-04-01 04:00:00 |     1 |   2 |   1  2024-04-01 05:00:00 |     1 |   2 |   2  2024-04-01 06:00:00 |     1 |   2 |   3  2024-04-01 07:00:00 |     1 |   2 |   4  2024-04-01 08:00:00 |     1 |   2 |   5  2024-04-01 09:00:00 |    -1 |   3 |  -1 (9 rows)<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u0437\u044f\u0442\u044c \u043f\u0435\u0440\u0432\u0443\u044e \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443 5-\u043a\u0443, \u0437\u0430\u0442\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0437\u0430 \u043d\u0435\u0439 -5, \u0437\u0430\u0442\u0435\u043c 6, -5, 7 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0434\u043b\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e (\u0447\u0438\u0442\u0430\u0439, \u0438\u0442\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e) \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u041d\u0443 \u0438 \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043b\u0435\u0438\u0442\u044c \u043f\u0430\u0440\u044b \u0441\u0442\u0440\u043e\u043a, \u0438\u0434\u0443\u0449\u0438\u0445 \u0434\u0440\u0443\u0433 \u0437\u0430 \u0434\u0440\u0443\u0433\u043e\u043c, \u0432 \u043e\u0434\u0438\u043d \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d, \u043a\u0430\u043a \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"pgsql\">WITH RECURSIVE grps AS (    SELECT ts,      CASE WHEN good THEN 1 ELSE -1 END grade,      count( change ) OVER (ORDER BY ts) grp    FROM (     SELECT ts, good,        CASE WHEN good != lag(good) OVER (ORDER BY ts) THEN 1 END change      FROM deeds   ) ), s AS (   SELECT ts, sum(grade) OVER (PARTITION BY grp ORDER BY ts) score   FROM grps ), r AS (    -- \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u043e\u0435 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 \u043f\u044f\u0442\u0435\u0440\u043a\u0438...   (SELECT ts, score,       score+0.5 AS score_plus -- \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e 0.5, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0440\u0430\u0441\u0442\u0430\u043b\u043e \u0437\u0430 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430    FROM s    WHERE score = 5     ORDER BY ts LIMIT 1   )   UNION ALL    -- ...\u0437\u0430\u0442\u0435\u043c -5, 6, -5, 7 \u0438 \u0442. \u0434., \u0447\u0435\u0440\u0435\u0434\u0443\u0435\u043c \u0437\u043d\u0430\u043a   (SELECT s.ts, s.score, r.score_plus+0.5     FROM s CROSS JOIN r    WHERE s.ts > r.ts       AND s.score = CASE WHEN r.score > 0 THEN -5 ELSE r.score_plus END     ORDER BY s.ts LIMIT 1   ) ) -- \u0441\u043a\u043b\u0435\u0438\u0432\u0430\u0435\u043c \u0434\u0432\u0435 \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d SELECT tsrange(ts, next_ts) FROM (   SELECT ts, lead(ts) OVER (ORDER BY ts) next_ts, score    FROM r ) WHERE score > 0 ORDER BY ts;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h4>\u041d\u0435 \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0442\u0430\u043a<\/h4>\n<ul>\n<li>\n<p>\u0412 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 \u0443\u043f\u043e\u0440\u044f\u0434\u043e\u0447\u0435\u043d\u044b \u043f\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u00f3\u0439 \u043c\u0435\u0442\u043a\u0435. \u041c\u043d\u043e\u0433\u0438\u0435 \u043f\u0440\u0438\u0434\u0435\u043b\u0430\u043b\u0438 \u0435\u0449\u0435 \u0438 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0438\u0439 \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0439 \u043d\u043e\u043c\u0435\u0440, \u043d\u043e \u0437\u0430\u0447\u0435\u043c? \u042d\u0442\u043e \u043b\u0438\u0448\u043d\u0438\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p>\u041d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043c\u0435\u043d\u0430 \u0442\u0440\u0430\u043d\u0441\u043b\u0438\u0442\u043e\u043c. \u0418\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0442\u0438\u043f\u0430 <code>kolvo<\/code> \u0438\u043b\u0438 <code>izmen<\/code> \u0441\u043c\u043e\u0442\u0440\u044f\u0442\u0441\u044f \u043e\u0447\u0435\u043d\u044c \u043d\u0435\u043f\u0440\u043e\u0444\u0435\u0441\u0441\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e.<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u0438\u043d\u043d\u044b\u0439 \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u043d\u044f\u0442\u043d\u043e\u0441\u0442\u0438, \u043d\u043e \u0435\u0441\u043b\u0438 \u043e\u043d \u0447\u0430\u0441\u0442\u043e \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0435\u0442\u0441\u044f, \u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043e\u0440\u0435\u0435 \u043c\u0435\u0448\u0430\u0442\u044c. \u041c\u043d\u0435 \u0441\u043b\u043e\u0436\u043d\u043e\u0432\u0430\u0442\u043e \u0447\u0438\u0442\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438:<br \/><code>SELECT sorted_deeds.deed_id, sorted_deeds.ts, sorted_deeds.good, CASE WHEN (sorted_deeds.good) AND (deeds_with_rating.rating > 0) THEN deeds_with_rating.rating + 1<\/code>.<br \/>\u041b\u0443\u0447\u0448\u0435 \u0441\u043e\u043a\u0440\u0430\u0442\u0438\u0442\u044c \u043f\u0441\u0435\u0432\u0434\u043e\u043d\u0438\u043c \u0434\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0431\u0443\u043a\u0432 \u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0444\u0440\u043e\u0432\u043a\u0443 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u041c\u043d\u043e\u0433\u0438\u0435 \u0437\u0430\u0447\u0435\u043c-\u0442\u043e \u0441\u0442\u0430\u043b\u0438 \u00ab\u043f\u043e\u0434\u0433\u043e\u043d\u044f\u0442\u044c\u00bb \u043e\u0442\u0432\u0435\u0442 \u043a \u0442\u043e\u043c\u0443 \u0432\u0438\u0434\u0443, \u043a\u0430\u043a \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u043f\u0440\u0438\u0432\u043e\u0434\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u043a \u0441\u0442\u0440\u043e\u043a\u0435 \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044f-\u0432\u044b\u0440\u0435\u0437\u0430\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u044b. \u042d\u0442\u043e\u0433\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u043e\u0441\u044c: \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 tsrange \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0432\u043e\u0434\u0438\u0442\u044c\u0441\u044f \u043f\u043e-\u0440\u0430\u0437\u043d\u043e\u043c\u0443 \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u043b\u043e\u043a\u0430\u043b\u0438. \u041d\u043e \u0441\u0438\u043b\u044c\u043d\u043e \u044f \u043a \u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u043f\u0440\u0438\u0434\u0438\u0440\u0430\u043b\u0441\u044f.<\/p>\n<\/li>\n<\/ul>\n<h2>\u0417\u0430\u0434\u0430\u0447\u0430 3. \u0428\u0430\u0445\u043c\u0430\u0442\u044b<\/h2>\n<h3>\u0423\u0441\u043b\u043e\u0432\u0438\u0435<\/h3>\n<p>\u0428\u0430\u0445\u043c\u0430\u0442\u043d\u0430\u044f \u043f\u0430\u0440\u0442\u0438\u044f (\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0435\u043e\u043a\u043e\u043d\u0447\u0435\u043d\u043d\u0430\u044f) \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u0430 \u0432 \u0432\u0438\u0434\u0435 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0438\u0306 \u0441\u0442\u0440\u043e\u043a\u0438 \u0432 <em>\u043f\u043e\u043b\u043d\u043e\u0438\u0306 \u043d\u043e\u0442\u0430\u0446\u0438\u0438<\/em>: <\/p>\n<ul>\n<li>\n<p>\u042d\u043b\u0435\u043c\u0435\u043d\u0442\u044b \u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u0442 \u0438\u0437 <em>\u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u043e\u0433\u043e \u043d\u043e\u043c\u0435\u0440\u0430 \u0445\u043e\u0434\u0430<\/em>, \u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0442 \u0442\u043e\u0447\u043a\u0430 \u0438 \u043f\u0440\u043e\u0431\u0435\u043b; \u0437\u0430\u0442\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u0435\u0442 <em>\u0437\u0430\u043f\u0438\u0441\u044c \u0445\u043e\u0434\u0430 \u0431\u0435\u043b\u044b\u0445<\/em>, \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u043e\u0431\u0435\u043b \u043c\u043e\u0436\u0435\u0442 \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c <em>\u0437\u0430\u043f\u0438\u0441\u044c \u0445\u043e\u0434\u0430 \u0447\u0435\u0440\u043d\u044b\u0445<\/em>. <\/p>\n<\/li>\n<li>\n<p>\u0417\u0430\u043f\u0438\u0441\u044c \u0445\u043e\u0434\u0430 (\u043a\u0430\u043a \u0431\u0435\u043b\u044b\u0445, \u0442\u0430\u043a \u0438 \u0447\u0435\u0440\u043d\u044b\u0445) \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 <em>\u0431\u0443\u043a\u0432\u0443<\/em>, \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u044e\u0449\u0443\u044e \u0444\u0438\u0433\u0443\u0440\u0443, \u0437\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0438\u0306 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 <em>\u0434\u0432\u0438\u0436\u0435\u043d\u0438\u044f <\/em>\u044d\u0442\u043e\u0438\u0306 \u0444\u0438\u0433\u0443\u0440\u044b. \u0421\u043f\u0438\u0441\u043e\u043a \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0445 \u0431\u0443\u043a\u0432: <\/p>\n<p><strong>\u2013 <\/strong><code>N<\/code> \u2014 \u043a\u043e\u043d\u044c (kNight);<br \/><strong>\u2013 <\/strong><code>B<\/code> \u2014 \u0441\u043b\u043e\u043d (Bishop);<br \/><strong>\u2013 <\/strong><code>R<\/code> \u2014 \u043b\u0430\u0434\u044c\u044f (Rook);<br \/><strong>\u2013 <\/strong><code>Q<\/code> \u2014 \u0444\u0435\u0440\u0437\u044c (Queen);<br \/><strong>\u2013 <\/strong><code>K<\/code> \u2014 \u043a\u043e\u0440\u043e\u043b\u044c (King); <\/p>\n<p>\u0415\u0441\u043b\u0438 \u0431\u0443\u043a\u0432\u0430 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u0445\u043e\u0434\u0438\u0442 \u043f\u0435\u0448\u043a\u0430 <code>p<\/code> (pawn).<\/p>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>\u0414\u0432\u0438\u0436\u0435\u043d\u0438\u0435 \u0444\u0438\u0433\u0443\u0440\u044b \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0434\u0440\u0443\u0433 \u0437\u0430 \u0434\u0440\u0443\u0433\u043e\u043c \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0438\u0306 <em>\u0434\u0432\u0443\u0445 \u043a\u043b\u0435\u0442\u043e\u043a<\/em>: <em>\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0438\u0306 <\/em>(\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u043e\u0438\u0306 \u0444\u0438\u0433\u0443\u0440\u0430 \u0441\u0442\u043e\u0438\u0442) \u0438 <em>\u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0438\u0306 <\/em>(\u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u0444\u0438\u0433\u0443\u0440\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u0441\u0442\u0438\u0442\u044c\u0441\u044f).<br \/>\u041f\u0440\u0438\u043c\u0435\u0440: <code>Ba1c3<\/code> \u2014 \u0441\u043b\u043e\u043d \u0438\u0434\u0435\u0442 \u0441 a1 \u043d\u0430 c3. <\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0441\u0432\u043e\u0438\u043c \u0445\u043e\u0434\u043e\u043c \u0444\u0438\u0433\u0443\u0440\u0430 \u0431\u044c\u0435\u0442 \u0444\u0438\u0433\u0443\u0440\u0443 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u0438\u043a\u0430, \u043f\u0435\u0440\u0435\u0434 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435\u043c \u0446\u0435\u043b\u0435\u0432\u043e\u0438\u0306 \u043a\u043b\u0435\u0442\u043a\u0438 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u0441\u0438\u043c\u0432\u043e\u043b \u0432\u0437\u044f\u0442\u0438\u044f <code>x<\/code>.<br \/>\u041f\u0440\u0438\u043c\u0435\u0440: <code>e4xd5<\/code> \u2014 \u043f\u0435\u0448\u043a\u0430 \u0441 e4 \u0431\u044c\u0435\u0442 \u043d\u0430 d5.<br \/>\u0412 \u044d\u0442\u043e\u043c \u0437\u0430\u0434\u0430\u043d\u0438\u0438 \u043d\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u0432\u0437\u044f\u0442\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0435. <\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0445\u043e\u0434 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0435\u0442\u0441\u044f \u0448\u0430\u0445\u043e\u043c, \u043f\u043e\u0441\u043b\u0435 \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0438\u0306 \u043a\u043b\u0435\u0442\u043a\u0438 \u0441\u0442\u0430\u0432\u0438\u0442\u0441\u044f \u0441\u0438\u043c\u0432\u043e\u043b <code>+<\/code>; \u0435\u0441\u043b\u0438 \u043c\u0430\u0442\u043e\u043c \u2014 \u0441\u0438\u043c\u0432\u043e\u043b <code>#<\/code>.<br \/>\u041f\u0440\u0438\u043c\u0435\u0440: <code>Qg3g7+<\/code> \u2014 \u0444\u0435\u0440\u0437\u044c \u0438\u0434\u0435\u0442 \u0441 g3 \u043d\u0430 g7 \u0438 \u0441\u0442\u0430\u0432\u0438\u0442 \u0448\u0430\u0445. <\/p>\n<\/li>\n<li>\n<p>\u0424\u0438\u0433\u0443\u0440\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043f\u0435\u0448\u043a\u0430, \u0434\u043e\u0438\u0306\u0434\u044f \u0434\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0438\u0306 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438, \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u044f \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0438\u0306 \u043a\u043b\u0435\u0442\u043a\u0438. \u041f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043f\u0435\u0448\u043a\u0430 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0444\u0435\u0440\u0437\u044f.<br \/>\u041f\u0440\u0438\u043c\u0435\u0440: <code>f7f8N#<\/code> \u2014 \u043f\u0435\u0448\u043a\u0430 \u0445\u043e\u0434\u0438\u0442 \u0441 f7 \u043d\u0430 f8, \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u043a\u043e\u043d\u0435\u043c \u0438 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u0442 \u043c\u0430\u0442. <\/p>\n<\/li>\n<li>\n<p>\u041a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442\u0441\u044f <code>O-O<\/code>, \u0434\u043b\u0438\u043d\u043d\u0430\u044f \u2014 <code>O-O-O<\/code>. <\/p>\n<\/li>\n<li>\n<p>\u0414\u0440\u0443\u0433\u0438\u0435 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f.  <\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0430\u0440\u0442\u0438\u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 <code>chess.game<\/code>. \u0418\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0442\u043e \u0432\u0441\u0435 \u0445\u043e\u0434\u044b \u0432 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0438\u0306 \u0437\u0430\u043f\u0438\u0441\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b, \u0442\u043e \u0435\u0441\u0442\u044c \u043d\u0435 \u043d\u0430\u0440\u0443\u0448\u0430\u044e\u0442 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u043f\u0440\u0430\u0432\u0438\u043b \u0438\u0433\u0440\u044b \u0432 \u0448\u0430\u0445\u043c\u0430\u0442\u044b.<\/p>\n<p>\u041d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u0437\u0430\u043f\u0440\u043e\u0441, \u0432\u044b\u0432\u043e\u0434\u044f\u0449\u0438\u0438\u0306 \u043f\u043e\u0437\u0438\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u043d\u0430 \u0448\u0430\u0445\u043c\u0430\u0442\u043d\u043e\u0438\u0306 \u0434\u043e\u0441\u043a\u0435 \u043f\u043e\u0441\u043b\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0445\u043e\u0434\u043e\u0432. \u041f\u043e\u0437\u0438\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0431\u044b\u0442\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u0430 \u043a\u0430\u043a \u043f\u043e\u043b\u0435 8\u00d78 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0441\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c\u0438 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u00ab<code> <\/code>\u00bb \u2014 \u043f\u0443\u0441\u0442\u043e\u0435 \u0431\u0435\u043b\u043e\u0435 \u043f\u043e\u043b\u0435, \u00ab<code>.<\/code>\u00bb \u2014 \u043f\u0443\u0441\u0442\u043e\u0435 \u0447\u0435\u0440\u043d\u043e\u0435 \u043f\u043e\u043b\u0435;<\/p>\n<\/li>\n<li>\n<p>\u00ab<code>P<\/code>\u00bb \u2014 \u0431\u0435\u043b\u0430\u044f \u043f\u0435\u0448\u043a\u0430, \u00ab<code>p<\/code>\u00bb \u2014 \u0447\u0435\u0440\u043d\u0430\u044f \u043f\u0435\u0448\u043a\u0430;<\/p>\n<\/li>\n<li>\n<p>\u00ab<code>N<\/code>\u00bb \u2014 \u0431\u0435\u043b\u044b\u0439 \u043a\u043e\u043d\u044c, \u00ab<code>n<\/code>\u00bb \u2014 \u0447\u0435\u0440\u043d\u044b\u0439 \u043a\u043e\u043d\u044c;<\/p>\n<\/li>\n<li>\n<p>\u00ab<code>B<\/code>\u00bb \u2014 \u0431\u0435\u043b\u044b\u0439 \u0441\u043b\u043e\u043d, \u00ab<code>b<\/code>\u00bb \u2014 \u0447\u0435\u0440\u043d\u044b\u0439 \u0441\u043b\u043e\u043d;<\/p>\n<\/li>\n<li>\n<p>\u00ab<code>R<\/code>\u00bb \u2014 \u0431\u0435\u043b\u0430\u044f \u043b\u0430\u0434\u044c\u044f, \u00ab<code>r<\/code>\u00bb \u2014 \u0447\u0435\u0440\u043d\u0430\u044f \u043b\u0430\u0434\u044c\u044f;<\/p>\n<\/li>\n<li>\n<p>\u00ab<code>Q<\/code>\u00bb \u2014 \u0431\u0435\u043b\u044b\u0439 \u0444\u0435\u0440\u0437\u044c, \u00ab<code>q<\/code>\u00bb \u2014 \u0447\u0435\u0440\u043d\u044b\u0439 \u0444\u0435\u0440\u0437\u044c;<\/p>\n<\/li>\n<li>\n<p>\u00ab<code>K<\/code>\u00bb \u2014 \u0431\u0435\u043b\u044b\u0439 \u043a\u043e\u0440\u043e\u043b\u044c, \u00ab<code>k<\/code>\u00bb \u2014 \u0447\u0435\u0440\u043d\u044b\u0439 \u043a\u043e\u0440\u043e\u043b\u044c.<\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0434\u0432\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u0430:<\/p>\n<ul>\n<li>\n<p><code>line<\/code> \u2014 \u043d\u043e\u043c\u0435\u0440 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438 \u043e\u0442 1 \u0434\u043e 8;<\/p>\n<\/li>\n<li>\n<p><code>chess<\/code> \u2014 \u0432\u043e\u0441\u0435\u043c\u044c \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 \u0434\u0430\u043d\u043d\u043e\u0439 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438, \u043e\u0442 a \u0434\u043e h.<\/p>\n<\/li>\n<\/ul>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440<\/h4>\n<p>\u0414\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 <\/p>\n<pre><code class=\"pgsql\">SET chess.game =   '1. e2e4 e7e5 2. Bf1c4 Nb8c6 3. Qd1h5 Ng8f6 4. Qh5xf7#';<\/code><\/pre>\n<p>\u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438: <\/p>\n<pre><code> line |  chess ------+----------     8 | r.bqkb r     7 | pppp.Qpp     6 |  .n. n .      5 | . . p .     4 |  .B.P. .     3 | . . . .     2 | PPPP PPP     1 | RNB K NR (8 rows)<\/code><\/pre>\n<h3>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 <\/h3>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u043e\u0432\u0435\u0440\u0445\u043d\u043e\u0441\u0442\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u0430 \u0441 \u0444\u043e\u0440\u043c\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u0430\u043c\u0438 \u0438\u0433\u0440\u044b. \u0415\u0441\u043b\u0438 \u0441 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u0432\u0437\u0433\u043b\u044f\u0434\u0430 \u043d\u0435\u043f\u043e\u043d\u044f\u0442\u043d\u043e, \u043a\u0430\u043a \u043f\u043e\u0434\u0441\u0442\u0443\u043f\u0438\u0442\u044c\u0441\u044f \u043a \u0437\u0430\u0434\u0430\u0447\u0435 \u2014 \u043d\u0435 \u0431\u0435\u0434\u0430, \u0441\u0435\u0439\u0447\u0430\u0441 \u0431\u0443\u0434\u0435\u043c \u0435\u0441\u0442\u044c \u044d\u0442\u043e\u0433\u043e \u0441\u043b\u043e\u043d\u0430 \u043f\u043e \u0447\u0430\u0441\u0442\u044f\u043c. \u042f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e \u0441\u0432\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u0430 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043f\u043e\u043a\u0430\u0436\u0443 \u0441\u043e\u0432\u0441\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u043f\u0435\u0440\u0432\u043e\u0435, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u2014 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0443 \u0441 \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u043f\u0430\u0440\u0442\u0438\u0438 \u0432 \u0443\u0434\u043e\u0431\u043e\u0432\u0430\u0440\u0438\u043c\u044b\u0439 \u0435\u0434\u0438\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u043d\u044b\u0439 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0439 \u0432\u0438\u0434. \u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0437\u0430\u043c\u0435\u0442\u0438\u043c: \u043d\u0438 \u0448\u0430\u0445\u043c\u0430\u0442\u043d\u0430\u044f \u043d\u0443\u043c\u0435\u0440\u0430\u0446\u0438\u044f \u0445\u043e\u0434\u043e\u0432, \u043d\u0438 \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u0432\u0437\u044f\u0442\u0438\u044f, \u0448\u0430\u0445\u0430 \u0438 \u043c\u0430\u0442\u0430 \u043d\u0430\u043c \u0441\u043e\u0432\u0435\u0440\u0448\u0435\u043d\u043d\u043e \u043d\u0435 \u043d\u0443\u0436\u043d\u044b. \u042d\u0442\u043e \u0447\u0438\u0441\u0442\u043e\u0439 \u0432\u043e\u0434\u044b \u0438\u0437\u0431\u044b\u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c, \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u0430\u043d\u043d\u0430\u044f \u043d\u0430 \u0432\u0435\u0447\u043d\u043e \u043e\u0448\u0438\u0431\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u043e\u0432. \u041e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0441\u0438\u043c\u0432\u043e\u043b\u044b \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0437\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0445\u043e\u0434\u044b \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u0433\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>regexp_matches<\/code>. <\/p>\n<p>\u041d\u0435\u043f\u043b\u043e\u0445\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u043e\u0434\u0441\u0442\u0435\u043b\u0438\u0442\u044c \u0441\u043e\u043b\u043e\u043c\u043a\u0438 \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <code>chess.game<\/code> \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f \u043f\u0443\u0441\u0442\u044b\u043c \u0438\u043b\u0438 \u0432\u043e\u043e\u0431\u0449\u0435 \u043d\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043d\u044b\u043c (\u044d\u0442\u043e \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0441\u044f \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0434\u0438\u043d \u0442\u043e\u043b\u044c\u043a\u043e \u0420\u0443\u0441\u043b\u0430\u043d \u041f\u0430\u0440\u0444\u0435\u043d\u043e\u0432, \u0445\u043e\u0442\u044f \u044f <a href=\"https:\/\/habr.com\/ru\/companies\/postgrespro\/articles\/742684\/\">\u043f\u0440\u0435\u0434\u0443\u043f\u0440\u0435\u0436\u0434\u0430\u043b \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437<\/a>).<\/p>\n<p>\u0417\u0430\u043e\u0434\u043d\u043e \u044f \u043f\u0440\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e \u043d\u043e\u043c\u0435\u0440 \u0438 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044e \u0446\u0432\u0435\u0442 \u0445\u043e\u0434\u044f\u0449\u0435\u0439 \u0444\u0438\u0433\u0443\u0440\u044b. \u0412\u043e\u0442 \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043a\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"pgsql\">-- \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043f\u0440\u0438\u043c\u0435\u0440 \u043f\u043e\u0441\u043b\u043e\u0436\u043d\u0435\u0435 SET chess.game = '1. e2e4 e7e5 2. Ng1f3 Nb8c6 3. Bf1c4 Bf8c5 4. b2b4 Bc5xb4 5. c2c3 Bb4a5 6. d2d4 e5xd4 7. O-O d4d3';  WITH rawmoves(n,color,move) AS (   -- \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0445\u043e\u0434\u044b \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0446\u0432\u0435\u0442   SELECT row_number() OVER() * 2,       CASE WHEN row_number() OVER() % 2 = 0 THEN 'B' ELSE 'W' END,      move[1]   FROM regexp_matches(        coalesce(translate(current_setting('chess.game',true),'x+#',''),'') || ' ',        '([a-h1-8RBNQKO-]+) ', 'g'      ) move ) SELECT * FROM rawmoves ORDER BY n;<\/code><\/pre>\n<pre><code> n  | color | move   ----+-------+-------   2 | W     | e2e4   4 | B     | e7e5   6 | W     | Ng1f3   8 | B     | Nb8c6  10 | W     | Bf1c4  12 | B     | Bf8c5  14 | W     | b2b4  16 | B     | Bc5b4  18 | W     | c2c3  20 | B     | Bb4a5  22 | W     | d2d4  24 | B     | e5d4  26 | W     | O-O  28 | B     | d4d3 (14 rows)<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u043d\u043e\u043c\u0435\u0440 \u0438\u0434\u0435\u0442 \u0441 \u0448\u0430\u0433\u043e\u043c 2. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043d\u0430\u043c \u043d\u0435\u0443\u0434\u043e\u0431\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u2014 \u043e\u043d\u0430 \u043d\u0435 \u0443\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u0449\u0443\u044e \u0441\u0445\u0435\u043c\u0443. \u041b\u0443\u0447\u0448\u0435 \u0437\u0430\u043c\u0435\u043d\u0438\u0442\u044c \u0435\u0435 \u043d\u0430 \u0434\u0432\u0430 \u043e\u0431\u044b\u0447\u043d\u044b\u0445 \u0445\u043e\u0434\u0430, \u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u043c \u0438 \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u043a \u043c\u0435\u0436\u0434\u0443 \u043d\u043e\u043c\u0435\u0440\u0430\u043c\u0438.<\/p>\n<pre><code class=\"pgsql\">WITH ... (   ... ), castling(color,move,n,newmove) AS (   VALUES -- \u0445\u043e\u0434\u044b \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a     ('W',   'O-O', 0, 'Rh1f1'),     ('W',   'O-O', 1, 'Ke1g1'),     ('W', 'O-O-O', 0, 'Ra1d1'),     ('W', 'O-O-O', 1, 'Ke1c1'),     ('B',   'O-O', 0, 'Rh8f8'),     ('B',   'O-O', 1, 'Ke8g8'),     ('B', 'O-O-O', 0, 'Ra8d8'),     ('B', 'O-O-O', 1, 'Ke8c8') ), castlingmoves(n,color,move) AS (   -- \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443 \u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0445\u043e\u0434\u044b   SELECT r.n+coalesce(c.n,0), r.color, coalesce(c.newmove,r.move)   FROM rawmoves r     LEFT JOIN castling c ON c.color = r.color AND c.move = r.move ) SELECT * FROM castlingmoves ORDER BY n;<\/code><\/pre>\n<pre><code> n  | color | move   ----+-------+-------   2 | W     | e2e4   4 | B     | e7e5   6 | W     | Ng1f3   8 | B     | Nb8c6  10 | W     | Bf1c4  12 | B     | Bf8c5  14 | W     | b2b4  16 | B     | Bc5b4  18 | W     | c2c3  20 | B     | Bb4a5  22 | W     | d2d4  24 | B     | e5d4  26 | W     | Rh1f1  27 | W     | Ke1g1  28 | B     | d4d3 (15 rows)<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0434\u043d\u043e\u0439 \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u0447\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 26 \u043f\u043e\u044f\u0432\u0438\u043b\u0438\u0441\u044c \u0441\u0442\u0440\u043e\u043a\u0438 26 \u0438 27 \u0441 \u0445\u043e\u0434\u0430\u043c\u0438 \u043b\u0430\u0434\u044c\u0438 \u0438 \u043a\u043e\u0440\u043e\u043b\u044f.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0437\u043e\u0431\u044c\u0435\u043c \u0445\u043e\u0434\u044b \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b: \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0444\u0438\u0433\u0443\u0440\u0443, \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c \u0438 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c, \u0438 \u0446\u0435\u043b\u0435\u0432\u044b\u0435 \u0444\u0438\u0433\u0443\u0440\u0443, \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c \u0438 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c. \u0418 \u0441\u043d\u043e\u0432\u0430 \u0443\u0434\u043e\u0431\u043d\u043e \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u043c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435\u043c:<\/p>\n<pre><code class=\"pgsql\">WITH ... AS (   ... ), components(n,color,piece_from,v_from,h_from,piece_to,v_to,h_to) AS (   -- \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0445\u043e\u0434 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b   SELECT n, color, coalesce(nullif(m[1],''),'P'),      nullif(m[2],''), nullif(m[3],''), nullif(m[6],''), m[4], m[5]   FROM (     SELECT n, color,       regexp_matches(move,'([RBNQK]?)([a-h]?)([1-8]?)([a-h])([1-8])([RBNQ])?') m     FROM castlingmoves   ) ) SELECT * FROM components ORDER BY n;<\/code><\/pre>\n<pre><code> n  | color | piece_from | v_from | h_from | piece_to | v_to | h_to  ----+-------+------------+--------+--------+----------+------+------   2 | W     | P          | e      | 2      |          | e    | 4   4 | B     | P          | e      | 7      |          | e    | 5   6 | W     | N          | g      | 1      |          | f    | 3   8 | B     | N          | b      | 8      |          | c    | 6  10 | W     | B          | f      | 1      |          | c    | 4  12 | B     | B          | f      | 8      |          | c    | 5  14 | W     | P          | b      | 2      |          | b    | 4  16 | B     | B          | c      | 5      |          | b    | 4  18 | W     | P          | c      | 2      |          | c    | 3  20 | B     | B          | b      | 4      |          | a    | 5  22 | W     | P          | d      | 2      |          | d    | 4  24 | B     | P          | e      | 5      |          | d    | 4  26 | W     | R          | h      | 1      |          | f    | 1  27 | W     | K          | e      | 1      |          | g    | 1  28 | B     | P          | d      | 4      |          | d    | 3 (15 rows)<\/code><\/pre>\n<p>\u041f\u0443\u0441\u0442\u0443\u044e \u0438\u0441\u0445\u043e\u0434\u043d\u0443\u044e \u0444\u0438\u0433\u0443\u0440\u0443 \u044f \u0437\u0430\u043c\u0435\u043d\u044f\u044e \u043d\u0430 <code>P<\/code>. \u0426\u0435\u043b\u0435\u0432\u0430\u044f \u0444\u0438\u0433\u0443\u0440\u0430 \u043f\u043e\u043a\u0430 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0435\u0439\u0441\u044f \u043f\u0435\u0448\u043a\u0438, \u043d\u043e \u044d\u0442\u043e \u043c\u044b \u0441\u043a\u043e\u0440\u043e \u0438\u0441\u043f\u0440\u0430\u0432\u0438\u043c. \u041a\u0441\u0442\u0430\u0442\u0438, \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c \u0438 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u044c \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0432 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u043e\u043c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438 \u044f \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0435\u0434\u043f\u043e\u043b\u0430\u0433\u0430\u044e \u0442\u0430\u043a\u0443\u044e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e\u0431\u044b \u0443\u0436\u0435 \u043d\u0435 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c\u0441\u044f \u043a \u044d\u0442\u043e\u043c\u0443.<\/p>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0448\u0442\u0440\u0438\u0445\u0438: \u043f\u0435\u0440\u0435\u043d\u0443\u043c\u0435\u0440\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u0445\u043e\u0434\u044b \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443, \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0431\u0443\u043a\u0432\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0435\u0439 \u043d\u0430 \u0447\u0438\u0441\u043b\u0430, \u0430\u043a\u043a\u0443\u0440\u0430\u0442\u043d\u043e \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0446\u0435\u043b\u0435\u0432\u0443\u044e \u0444\u0438\u0433\u0443\u0440\u0443 \u0432\u043e \u0432\u0441\u0435\u0445 \u0441\u0442\u0440\u043e\u043a\u0430\u0445, \u0438 \u0432\u0441\u0435 \u0447\u0435\u0440\u043d\u044b\u0435 \u0444\u0438\u0433\u0443\u0440\u044b \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043c \u043a \u043d\u0438\u0436\u043d\u0435\u043c\u0443 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0443 \u2014 \u043a\u0430\u043a \u043d\u0430 \u0438\u0433\u0440\u043e\u0432\u043e\u043c \u043f\u043e\u043b\u0435. \u041f\u043e\u0441\u043b\u0435 \u044d\u0442\u043e\u0433\u043e \u0446\u0432\u0435\u0442 \u043d\u0430\u043c \u0443\u0436\u0435 \u043d\u0435 \u043d\u0443\u0436\u0435\u043d.<\/p>\n<pre><code class=\"pgsql\">WITH ... AS (   ... ), moves(n,piece_from,v_from,h_from,piece_to,v_to,h_to) AS (   SELECT n,       CASE WHEN color = 'B' THEN lower(piece_from) ELSE piece_from END,     v_from, h_from,     CASE WHEN color = 'B' THEN lower(piece_to) ELSE piece_to END,     v_to, h_to   FROM (     SELECT row_number() OVER (ORDER BY n) AS n,       color,       piece_from,       ascii(v_from) - ascii('a') + 1 AS v_from,       nullif(h_from,'')::integer AS h_from,       coalesce(piece_to,         CASE           WHEN piece_from = 'P' AND h_to IN ('1','8') THEN 'Q'            ELSE piece_from         END) AS piece_to,       ascii(v_to) - ascii('a') + 1 AS v_to,       nullif(h_to,'')::integer AS h_to     FROM components   ) ) SELECT * FROM moves ORDER BY n;<\/code><\/pre>\n<pre><code> n  | piece_from | v_from | h_from | piece_to | v_to | h_to  ----+------------+--------+--------+----------+------+------   1 | P          |      5 |      2 | P        |    5 |    4   2 | p          |      5 |      7 | p        |    5 |    5   3 | N          |      7 |      1 | N        |    6 |    3   4 | n          |      2 |      8 | n        |    3 |    6   5 | B          |      6 |      1 | B        |    3 |    4   6 | b          |      6 |      8 | b        |    3 |    5   7 | P          |      2 |      2 | P        |    2 |    4   8 | b          |      3 |      5 | b        |    2 |    4   9 | P          |      3 |      2 | P        |    3 |    3  10 | b          |      2 |      4 | b        |    1 |    5  11 | P          |      4 |      2 | P        |    4 |    4  12 | p          |      5 |      5 | p        |    4 |    4  13 | R          |      8 |      1 | R        |    6 |    1  14 | K          |      5 |      1 | K        |    7 |    1  15 | p          |      4 |      4 | p        |    4 |    3 (15 rows)<\/code><\/pre>\n<p>\u041d\u0443 \u0432\u043e\u0442, \u0441 \u0442\u0430\u043a\u0438\u043c \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c. \u0422\u0435\u043f\u0435\u0440\u044c \u043d\u0430\u043c \u043d\u0430\u0434\u043e \u0438\u0437\u043e\u0431\u0440\u0430\u0437\u0438\u0442\u044c \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0444\u0438\u0433\u0443\u0440 \u043d\u0430 \u0434\u043e\u0441\u043a\u0435 \u0432 \u0432\u0438\u0434\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b: \u043d\u043e\u043c\u0435\u0440 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438, \u043d\u043e\u043c\u0435\u0440 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438, \u0444\u0438\u0433\u0443\u0440\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0442\u0430\u043a:<\/p>\n<pre><code class=\"pgsql\">WITH ... (   ... ), board(v,h,p) AS (   -- \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f (\u0432\u0441\u0435 \u043a\u043b\u0435\u0442\u043a\u0438)   VALUES   (1,1,'R'),(2,1,'N'),(3,1,'B'),(4,1,'Q'),(5,1,'K'),(6,1,'B'),(7,1,'N'),(8,1,'R'),   (1,2,'P'),(2,2,'P'),(3,2,'P'),(4,2,'P'),(5,2,'P'),(6,2,'P'),(7,2,'P'),(8,2,'P'),   (1,7,'p'),(2,7,'p'),(3,7,'p'),(4,7,'p'),(5,7,'p'),(6,7,'p'),(7,7,'p'),(8,7,'p'),   (1,8,'r'),(2,8,'n'),(3,8,'b'),(4,8,'q'),(5,8,'k'),(6,8,'b'),(7,8,'n'),(8,8,'r')   UNION ALL    SELECT v, h, ' ' FROM generate_series(1,8) v, generate_series(3,6) h ) ...<\/code><\/pre>\n<p>\u041f\u0443\u0441\u0442\u044b\u0435 \u043a\u043b\u0435\u0442\u043a\u0438 \u2014 \u043f\u0440\u043e\u0431\u0435\u043b\u044b. \u041f\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044e \u0447\u0435\u0440\u043d\u044b\u0435 \u043a\u043b\u0435\u0442\u043a\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0431\u043e\u0437\u043d\u0430\u0447\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u0447\u043a\u0430\u043c\u0438, \u043d\u043e \u0441\u0435\u0439\u0447\u0430\u0441 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u0435\u0448\u0430\u0442\u044c.<\/p>\n<p>\u041d\u0430\u043c \u043e\u0441\u0442\u0430\u043b\u0438\u0441\u044c \u0441\u0443\u0449\u0438\u0435 \u043f\u0443\u0441\u0442\u044f\u043a\u0438: \u00ab\u043f\u0440\u043e\u0438\u0433\u0440\u0430\u0442\u044c\u00bb \u043a\u0430\u0436\u0434\u044b\u0439 \u0445\u043e\u0434 \u043f\u0430\u0440\u0442\u0438\u0438, \u0438\u0437\u043c\u0435\u043d\u044f\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f. \u0421 \u044d\u0442\u0438\u043c \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441. \u041d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438, \u0430 \u043d\u0430 \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u043c \u0445\u043e\u0434\u0443 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u043f\u043e\u0437\u0438\u0446\u0438\u044e \u0441 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u043d\u043e\u0439 \u0440\u0430\u043d\u0435\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u0435\u0439 <code>moves<\/code>: \u043d\u0430 \u0442\u0443 \u043a\u043b\u0435\u0442\u043a\u0443, \u0441 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0443\u0448\u043b\u0430 \u0444\u0438\u0433\u0443\u0440\u0430, \u0441\u0442\u0430\u0432\u0438\u043c \u043f\u0440\u043e\u0431\u0435\u043b; \u043d\u0430 \u0442\u0443 \u043a\u043b\u0435\u0442\u043a\u0443, \u043a\u0443\u0434\u0430 \u0444\u0438\u0433\u0443\u0440\u0430 \u043f\u0440\u0438\u0448\u043b\u0430, \u0441\u0442\u0430\u0432\u0438\u043c \u0441\u0438\u043c\u0432\u043e\u043b \u0444\u0438\u0433\u0443\u0440\u044b (\u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043c\u044b \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u00ab\u0437\u0430\u0442\u0440\u0435\u043c\u00bb \u0444\u0438\u0433\u0443\u0440\u0443 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u0438\u043a\u0430, \u0435\u0441\u043b\u0438 \u0435\u0439 \u043d\u0435 \u043f\u043e\u0441\u0447\u0430\u0441\u0442\u043b\u0438\u0432\u0438\u043b\u043e\u0441\u044c \u043e\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f \u0432\u0437\u044f\u0442\u043e\u0439); \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043b\u0435\u0442\u043a\u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439. <\/p>\n<pre><code class=\"pgsql\">WITH RECURSIVE ... (   ... ), game(n,v,h,p) AS (   -- \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438   SELECT 1, v, h, p    FROM board   UNION ALL                         -- \u0434\u0435\u043b\u0430\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0448\u0430\u0433   SELECT g.n+1, v, h,      CASE        WHEN v=v_to   AND h=h_to   THEN piece_to       WHEN v=v_from AND h=h_from THEN ' '       ELSE p      END   FROM game g     JOIN moves m ON m.n = g.n  ) ...<\/code><\/pre>\n<p>\u041d\u0430 \u043a\u0430\u0436\u0434\u043e\u043c \u0445\u043e\u0434\u0443 \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0443\u0442 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c\u0441\u044f 8\u00d78=64 \u0441\u0442\u0440\u043e\u043a\u0438, \u0447\u0442\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0442\u0435\u0440\u043f\u0438\u043c\u043e \u0434\u043b\u044f \u043f\u0430\u0440\u0442\u0438\u0438 \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043e\u0442\u0435\u043d \u0445\u043e\u0434\u043e\u0432. \u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044e \u0438 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c, \u0432 \u0443\u0434\u043e\u0431\u043e\u0432\u0430\u0440\u0438\u043c\u043e\u043c \u0432\u0438\u0434\u0435, \u043f\u043e\u043f\u0443\u0442\u043d\u043e \u0437\u0430\u043c\u0435\u043d\u044f\u044f \u043f\u0443\u0441\u0442\u044b\u0435 \u0447\u0435\u0440\u043d\u044b\u0435 \u043a\u043b\u0435\u0442\u043a\u0438 \u0442\u043e\u0447\u043a\u0430\u043c\u0438:<\/p>\n<pre><code class=\"pgsql\">WITH RECURSIVE ... (   ... ), last_position AS (   -- \u0431\u0435\u0440\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044e   SELECT * FROM game WHERE n = (SELECT max(n) FROM game) ) -- \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 SELECT h.h AS line,   string_agg(     CASE WHEN b.p = ' ' AND (v.v+h.h) % 2 = 0 THEN '.' ELSE b.p END,     '' ORDER BY v.v   ) AS chess FROM generate_series(1,8) h(h)   CROSS JOIN generate_series(1,8) v(v)   LEFT JOIN last_position b ON b.h = h.h AND b.v = v.v GROUP BY h.h ORDER BY h.h DESC;<\/code><\/pre>\n<pre><code> line |  chess    ------+----------     8 | r.bqk.nr     7 | pppp.ppp     6 |  .n. . .     5 | b . . .      4 |  .B.P. .     3 | . Pp.N.      2 | P. . PPP     1 | RNBQ.RK  (8 rows)<\/code><\/pre>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"pgsql\">WITH RECURSIVE rawmoves(n,color,move) AS (   -- \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0445\u043e\u0434\u044b \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0446\u0432\u0435\u0442   SELECT row_number() over() * 2,       CASE WHEN row_number() over() % 2 = 0 THEN 'B' ELSE 'W' END,      move[1]   FROM regexp_matches(        coalesce(translate(current_setting('chess.game',true),'x+#',''),'') || ' ',        '([a-h1-8RBNQKO-]+) ', 'g'      ) move ), castling(color,move,n,newmove) AS (   VALUES -- \u0445\u043e\u0434\u044b \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a     ('W',   'O-O', 0, 'Rh1f1'),     ('W',   'O-O', 1, 'Ke1g1'),     ('W', 'O-O-O', 0, 'Ra1d1'),     ('W', 'O-O-O', 1, 'Ke1c1'),     ('B',   'O-O', 0, 'Rh8f8'),     ('B',   'O-O', 1, 'Ke8g8'),     ('B', 'O-O-O', 0, 'Ra8d8'),     ('B', 'O-O-O', 1, 'Ke8c8') ), castlingmoves(n,color,move) AS (   -- \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443 \u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0445\u043e\u0434\u044b   SELECT r.n+coalesce(c.n,0), r.color, coalesce(c.newmove,r.move)   FROM rawmoves r     LEFT JOIN castling c ON c.color = r.color AND c.move = r.move ), components(n,color,piece_from,v_from,h_from,piece_to,v_to,h_to) AS (   -- \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0445\u043e\u0434 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b   SELECT n, color, coalesce(nullif(m[1],''),'P'),      nullif(m[2],''), nullif(m[3],''), nullif(m[6],''), m[4], m[5]   FROM (     SELECT n, color,       regexp_matches(move,'([RBNQK]?)([a-h]?)([1-8]?)([a-h])([1-8])([RBNQ])?') m     FROM castlingmoves   ) ), moves(n,piece_from,v_from,h_from,piece_to,v_to,h_to) AS (   SELECT n,     CASE WHEN color = 'B' THEN lower(piece_from) ELSE piece_from END,     v_from, h_from,     CASE WHEN color = 'B' THEN lower(piece_to) ELSE piece_to END,     v_to, h_to   FROM (     SELECT row_number() OVER (ORDER BY n) AS n,       color,       piece_from,       ascii(v_from) - ascii('a') + 1 AS v_from,       nullif(h_from,'')::integer AS h_from,       coalesce(piece_to,         CASE           WHEN piece_from = 'P' AND h_to IN ('1','8') THEN 'Q'           ELSE piece_from         END) AS piece_to,       ascii(v_to) - ascii('a') + 1 AS v_to,       nullif(h_to,'')::integer AS h_to     FROM components   ) ), board(v,h,p) AS (   -- \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f (\u0432\u0441\u0435 \u043a\u043b\u0435\u0442\u043a\u0438)   VALUES   (1,1,'R'),(2,1,'N'),(3,1,'B'),(4,1,'Q'),(5,1,'K'),(6,1,'B'),(7,1,'N'),(8,1,'R'),   (1,2,'P'),(2,2,'P'),(3,2,'P'),(4,2,'P'),(5,2,'P'),(6,2,'P'),(7,2,'P'),(8,2,'P'),   (1,7,'p'),(2,7,'p'),(3,7,'p'),(4,7,'p'),(5,7,'p'),(6,7,'p'),(7,7,'p'),(8,7,'p'),   (1,8,'r'),(2,8,'n'),(3,8,'b'),(4,8,'q'),(5,8,'k'),(6,8,'b'),(7,8,'n'),(8,8,'r')   UNION ALL   SELECT v, h, ' ' FROM generate_series(1,8) v, generate_series(3,6) h ), game(n,v,h,p) AS (   -- \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438   SELECT 1, v, h, p   FROM board   UNION ALL   -- \u0434\u0435\u043b\u0430\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0448\u0430\u0433   SELECT g.n+1, v, h,     CASE       WHEN v=v_to   AND h=h_to   THEN piece_to       WHEN v=v_from AND h=h_from THEN ' '       ELSE p     END   FROM game g     JOIN moves m ON m.n = g.n ), last_board AS (   -- \u0431\u0435\u0440\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044e   SELECT * FROM game WHERE n = (SELECT max(n) FROM game) ) -- \u043a\u0440\u0430\u0441\u0438\u0432\u043e \u0432\u044b\u0432\u043e\u0434\u0438\u043c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 SELECT h.h AS line,   string_agg(     CASE WHEN b.p = ' ' AND (v.v+h.h) % 2 = 0 THEN '.' ELSE b.p END,     '' ORDER BY v.v   ) AS chess FROM generate_series(1,8) h(h)   CROSS JOIN generate_series(1,8) v(v)   LEFT JOIN last_board b ON b.h = h.h AND b.v = v.v GROUP BY h.h ORDER BY h.h DESC;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0410 \u0432\u043e\u0442 \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0410\u0440\u0442\u0435\u043c\u0430 \u0421\u0443\u0445\u043e\u0432\u0430. \u0412 \u043d\u0435\u043c \u0445\u043e\u0434\u044b \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435, \u0430 \u043f\u043e\u043b\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c jsonb: \u043a\u043b\u044e\u0447 \u2014 \u043d\u043e\u043c\u0435\u0440 \u043a\u043b\u0435\u0442\u043a\u0438, \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 \u2014 \u0444\u0438\u0433\u0443\u0440\u0430 \u0432 \u044d\u0442\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0435. \u0412 jsonb \u043d\u0435 \u0431\u044b\u0432\u0430\u0435\u0442 \u0434\u0443\u0431\u043b\u0438\u043a\u0430\u0442\u043e\u0432 \u043a\u043b\u044e\u0447\u0435\u0439, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043a\u043b\u044e\u0447\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043f\u0435\u0440\u0435\u0437\u0430\u043f\u0438\u0441\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f (\u043e\u0431 \u044d\u0442\u043e\u043c, \u043a\u0441\u0442\u0430\u0442\u0438, \u0441\u0442\u043e\u0438\u043b\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445).<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0410\u0440\u0442\u0435\u043c\u0430 \u0421\u0443\u0445\u043e\u0432\u0430<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"pgsql\">-- \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0442\u0440\u043e\u0438\u0442\u0441\u044f \u043d\u0430 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0445\u043e\u0434\u0430 -- \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u0438\u0437 \u0434\u0430\u043d\u043d\u044b\u0445: \u043f\u043e\u0440\u044f\u0434\u043a\u043e\u0432\u044b\u0439 \u043d\u043e\u043c\u0435\u0440 \u0445\u043e\u0434\u0430, \u0445(\u0443\u0431\u0438\u0439\u0441\u0442\u0432\u043e), +(\u0448\u0430\u0445), #(\u043c\u0430\u0442) \u0434\u043b\u044f \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0441\u0438\u043d\u0433\u0430 WITH RECURSIVE input as (   SELECT regexp_replace((select current_setting('chess.game')), '\\d+\\. |[x+#]', '', 'g') AS data ) -- \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0438\u0433\u0440\u043e\u0432\u043e\u0439 \u0434\u043e\u0441\u043a\u0438 \u043f\u043e\u0441\u043b\u0435 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0448\u0430\u0433\u0430 ,moves as (   select 0 as move_number        -- \u043c\u0430\u0441\u0441\u0438\u0432 \u0445\u043e\u0434\u043e\u0432        , string_to_array((select data from input), ' ') as moves_array        -- \u0438\u0433\u0440\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435        , '{\"a1\" : \"R\", \"a2\" : \"P\", \"a3\" : \" \", \"a4\" : \" \", \"a5\" : \" \", \"a6\" : \" \", \"a7\" : \"p\", \"a8\" : \"r\"           ,\"b1\" : \"N\", \"b2\" : \"P\", \"b3\" : \" \", \"b4\" : \" \", \"b5\" : \" \", \"b6\" : \" \", \"b7\" : \"p\", \"b8\" : \"n\"           ,\"c1\" : \"B\", \"c2\" : \"P\", \"c3\" : \" \", \"c4\" : \" \", \"c5\" : \" \", \"c6\" : \" \", \"c7\" : \"p\", \"c8\" : \"b\"           ,\"d1\" : \"Q\", \"d2\" : \"P\", \"d3\" : \" \", \"d4\" : \" \", \"d5\" : \" \", \"d6\" : \" \", \"d7\" : \"p\", \"d8\" : \"q\"           ,\"e1\" : \"K\", \"e2\" : \"P\", \"e3\" : \" \", \"e4\" : \" \", \"e5\" : \" \", \"e6\" : \" \", \"e7\" : \"p\", \"e8\" : \"k\"           ,\"f1\" : \"B\", \"f2\" : \"P\", \"f3\" : \" \", \"f4\" : \" \", \"f5\" : \" \", \"f6\" : \" \", \"f7\" : \"p\", \"f8\" : \"b\"           ,\"g1\" : \"N\", \"g2\" : \"P\", \"g3\" : \" \", \"g4\" : \" \", \"g5\" : \" \", \"g6\" : \" \", \"g7\" : \"p\", \"g8\" : \"n\"           ,\"h1\" : \"R\", \"h2\" : \"P\", \"h3\" : \" \", \"h4\" : \" \", \"h5\" : \" \", \"h6\" : \" \", \"h7\" : \"p\", \"h8\" : \"r\"         }'::jsonb as chessboard   union ALL   select move_number + 1        -- \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0435\u0441\u044f \u0448\u0430\u0433\u0438 \u0432 \u043f\u0430\u0440\u0442\u0438\u0438        , moves_array[2:array_length(moves_array, 1)] AS moves_array        -- \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c \u0438\u0433\u0440\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435. \u043a\u043e\u0440\u043e\u0442\u043a\u0430\u044f \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430        , case when moves_array[1] = 'O-O'               -- \u0435\u0441\u043b\u0438 \u0445\u043e\u0434\u0438\u0442 \u043f\u0435\u0440\u0432\u044b\u0439 \u0438\u0433\u0440\u043e\u043a               then case when mod(move_number+1, 2) = 1                         then chessboard ||                               '{\"e1\": \" \"}'::jsonb ||                              '{\"h1\": \" \"}'::jsonb ||                               '{\"g1\": \"K\"}'::jsonb ||                               '{\"f1\": \"R\"}'::jsonb                         else chessboard ||                               '{\"e8\": \" \"}'::jsonb ||                               '{\"h8\": \" \"}'::jsonb ||                               '{\"g8\": \"k\"}'::jsonb ||                               '{\"f8\": \"r\"}'::jsonb end               -- \u0434\u043b\u0438\u043d\u043d\u0430\u044f \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430               else case when moves_array[1] = 'O-O-O'                     then case when mod(move_number+1, 2) = 1                          then chessboard ||                               '{\"e1\": \" \"}'::jsonb ||                               '{\"a1\": \" \"}'::jsonb ||                               '{\"c1\": \"K\"}'::jsonb ||                               '{\"d1\": \"R\"}'::jsonb                         else chessboard ||                               '{\"e8\": \" \"}'::jsonb ||                               '{\"a8\": \" \"}'::jsonb ||                               '{\"c8\": \"k\"}'::jsonb ||                               '{\"d8\": \"r\"}'::jsonb end        -- \u0435\u0441\u043b\u0438 \u043d\u0435 \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430        else chessboard ||          -- \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u0444\u0438\u0433\u0443\u0440\u0443 \u0438\u0437 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438          ('{\"' || (regexp_match(moves_array[1], '([a-h][1-8])'))[1] || '\": \" \"}')::jsonb ||          -- \u0441\u0442\u0430\u0432\u0438\u043c \u0444\u0438\u0433\u0443\u0440\u0443 \u043d\u0430 \u043a\u043e\u043d\u0435\u0447\u043d\u0443\u044e \u043f\u043e\u0437\u0438\u0446\u0438\u044e          ('{\"' || (regexp_match(moves_array[1], '[a-h][1-8].*?([a-h][1-8])'))[1] || '\": \"'||          case when mod(move_number+1, 2) = 1               -- \u0448\u0430\u0433 \u0434\u043b\u0438\u043d\u044b 5 = \u0438\u043b\u0438 \u0445\u043e\u0434 \u041d\u0415 \u043f\u0435\u0448\u043a\u0438, \u0438\u043b\u0438 \u044f\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043f\u0435\u0448\u043a\u0438               then upper(case when length(moves_array[1]) = 5                                then case when substring(moves_array[1], 1, 1) in ('N', 'B', 'R', 'Q', 'K')                                         then substring(moves_array[1], 1, 1)                                         else substring(moves_array[1], 5, 1) end                               -- \u0438\u043d\u0430\u0447\u0435 \u0438\u043b\u0438 \u043d\u0435\u044f\u0432\u043d\u043e\u0435 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043f\u0435\u0448\u043a\u0438                               else case when substring(moves_array[1], 4, 1) in ('1', '8')                                          then 'Q'                               -- \u0438\u043d\u0430\u0447\u0435 \u0445\u043e\u0434 \u043f\u0435\u0448\u043a\u0438                                         else 'P' end                           end)               else lower(case when length(moves_array[1]) = 5                                then case when substring(moves_array[1], 1, 1) in ('N', 'B', 'R', 'Q', 'K')                                         then substring(moves_array[1], 1, 1)                                         else substring(moves_array[1], 5, 1) end                               else case when substring(moves_array[1], 4, 1) in ('1', '8')                                          then 'Q'                                         else 'P' end                           end) end                                                 ||'\"}')::jsonb end end   FROM moves   WHERE move_number &lt; array_length(string_to_array((select data from input), ' '), 1) ) -- \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c jsonb \u043d\u0430 \u0441\u0442\u043e\u043b\u0431\u0446\u044b \u0438 \u0441\u0442\u0440\u043e\u043a\u0438 \u0434\u043b\u044f \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0438\u0433\u0440\u043e\u0432\u043e\u0433\u043e \u043f\u043e\u043b\u044f , cells_data as ( select (regexp_match(key, '\\d'))[1]::int as line      , row_number() over(partition by (regexp_match(key, '\\d'))[1] order by key) as col      , key      , value   -- \u0431\u0435\u0440\u0435\u043c \u0438\u0433\u0440\u043e\u0432\u0443\u044e \u0434\u043e\u0441\u043a\u0443 \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0433\u043e \u0445\u043e\u0434\u0430   from jsonb_each_text((select chessboard                           from moves                          where move_number = (select max(move_number) from moves))) ) select line, string_agg(case when value != ' '                              then value                             else case when mod(line+col, 2) = 0 then '.' else ' ' end end, '' order by key) as chess   from cells_data  group by line  order by line desc<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<h4>\u041d\u0435 \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0442\u0430\u043a<\/h4>\n<ul>\n<li>\n<p>\u041f\u043e\u0447\u0435\u043c\u0443-\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432 \u0432\u0437\u044f\u043b\u0438\u0441\u044c \u043d\u0443\u043c\u0435\u0440\u043e\u0432\u0430\u0442\u044c \u043f\u0443\u043d\u043a\u0442\u044b \u0440\u0435\u0448\u0435\u043d\u0438\u044f. \u0414\u043e\u0445\u043e\u0434\u0438\u043b\u043e \u0434\u0430\u0436\u0435 \u0434\u043e \u0442\u0430\u043a\u043e\u0433\u043e:<br \/><code>-- 2.2.1.2.5 \u041f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u0432 \u0441\u043b\u043e\u043d\u0430<\/code><br \/>\u041d\u0435 \u043c\u043e\u0433\u0443 \u043d\u0430\u0439\u0442\u0438 \u0432 \u044d\u0442\u043e\u043c \u0441\u043c\u044b\u0441\u043b\u0430. \u041a\u043e\u043c\u0443 \u0438 \u043e \u0447\u0435\u043c \u043c\u043e\u0433\u0443\u0442 \u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c \u044d\u0442\u0438 \u043d\u043e\u043c\u0435\u0440\u0430?<\/p>\n<\/li>\n<li>\n<p>\u0412 PostgreSQL \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043f\u0438\u0441\u0430\u0442\u044c <code>SELECT ... UNION ALL SELECT ... UNION ALL ...<\/code>, \u043a\u043e\u0433\u0434\u0430 \u043d\u0430\u0434\u043e \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0441\u0442\u0440\u043e\u043a. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043b\u0430\u043a\u043e\u043d\u0438\u0447\u043d\u0430\u044f \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u044f <code>VALUES<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0427\u0442\u043e\u0431\u044b \u043d\u0430\u0431\u0440\u0430\u0442\u044c \u0441\u043a\u043e\u043b\u044c\u043a\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0431\u0430\u043b\u043b\u043e\u0432 \u0437\u0430 \u0437\u0430\u0434\u0430\u0447\u0443, \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c\u0443\u044e \u0442\u0435\u0441\u0442\u0430\u043c\u0438, \u043d\u0430\u0434\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0445\u043e\u0442\u044f \u0431\u044b \u0447\u0430\u0441\u0442\u044c \u0437\u0430\u0434\u0430\u043d\u0438\u044f, \u043d\u043e \u0434\u043e \u043a\u043e\u043d\u0446\u0430. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0441\u0435\u0433\u043e, \u043a\u0440\u043e\u043c\u0435 \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0438 \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0435\u043d\u0438\u0439 \u043f\u0435\u0448\u0435\u043a, \u0434\u0430\u0432\u0430\u043b\u0430 \u0432\u043f\u043e\u043b\u043d\u0435 \u0441\u043e\u043b\u0438\u0434\u043d\u044b\u0435 8 \u0431\u0430\u043b\u043b\u043e\u0432. \u0415\u0441\u043b\u0438 \u0436\u0435 \u0437\u0430\u0434\u0430\u0447\u0430 \u00ab\u043f\u043e\u0447\u0442\u0438 \u0440\u0435\u0448\u0435\u043d\u0430\u00bb, \u043d\u043e \u043d\u0435 \u043f\u0440\u043e\u0445\u043e\u0434\u0438\u0442 \u043d\u0438 \u043e\u0434\u043d\u043e\u0433\u043e \u0442\u0435\u0441\u0442\u0430 \u2014 \u0443\u0432\u044b, \u043e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0441\u043e\u0447\u0443\u0432\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p>\u041a\u0430\u043f\u0438\u0442\u0430\u043d\u0441\u043a\u0438\u0439 \u0441\u043e\u0432\u0435\u0442: \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043c\u043e\u0436\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u0438\u0437 \u0441\u0431\u043e\u0440\u043d\u0438\u043a\u0430 \u0448\u0430\u0445\u043c\u0430\u0442\u043d\u044b\u0445 \u0437\u0430\u0434\u0430\u0447 \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u0438\u0437 \u0432\u0438\u043a\u0438\u043f\u0435\u0434\u0438\u0438 \u043a\u0430\u043a\u0443\u044e-\u043d\u0438\u0431\u0443\u0434\u044c \u043f\u0430\u0440\u0442\u0438\u044e, \u0434\u043b\u044f \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u0430 \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f.<\/p>\n<\/li>\n<\/ul>\n<h2>\u0417\u0430\u0434\u0430\u0447\u0430 4. \u0428\u0430\u0445\u043c\u0430\u0442\u044b (\u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0435\u043d\u0438\u0435)<\/h2>\n<h3>\u0423\u0441\u043b\u043e\u0432\u0438\u0435<\/h3>\n<p>\u041f\u043e\u043b\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u0448\u0430\u0445\u043c\u0430\u0442\u043d\u043e\u0438\u0306 \u043f\u0430\u0440\u0442\u0438\u0438 \u0438\u0437 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0438\u0306 \u0437\u0430\u0434\u0430\u0447\u0438 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0430: \u0432 \u043d\u0435\u0438\u0306 \u0440\u0430\u0437\u0440\u0435\u0448\u0430\u0435\u0442\u0441\u044f \u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0442\u0435\u043a\u0443\u0449\u0435\u0433\u043e \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0444\u0438\u0433\u0443\u0440\u044b \u2014 \u043b\u0438\u0431\u043e \u0446\u0435\u043b\u0438\u043a\u043e\u043c, \u043b\u0438\u0431\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u043d\u043e\u0438\u0306 \u0438\u0437 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u2014 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0442\u0430\u043a\u043e\u0435 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u0438\u0435 \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043b\u043e \u043a \u043d\u0435\u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e\u0441\u0442\u0438. <\/p>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b: <\/p>\n<ul>\n<li>\n<p><code>Rb7<\/code> \u2014 \u043b\u0430\u0434\u044c\u044f \u0438\u0434\u0435\u0442 \u043d\u0430 b7 (\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u043e, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442 \u0434\u0440\u0443\u0433\u043e\u0438\u0306 \u043b\u0430\u0434\u044c\u0438, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043c\u043e\u0436\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0442\u0430\u043a\u043e\u0438\u0306 \u0436\u0435 \u0445\u043e\u0434); <\/p>\n<\/li>\n<li>\n<p><code>R6b7<\/code> \u2014 \u043b\u0430\u0434\u044c\u044f \u0438\u0434\u0435\u0442 \u043d\u0430 b7 \u0441 \u0448\u0435\u0441\u0442\u043e\u0438\u0306 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438 (\u0443\u0442\u043e\u0447\u043d\u0435\u043d\u0438\u0435 \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f, \u0435\u0441\u043b\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u0440\u0443\u0433\u0430\u044f \u043b\u0430\u0434\u044c\u044f \u0441\u0442\u043e\u0438\u0442 \u043d\u0430 b8); <\/p>\n<\/li>\n<li>\n<p><code>Rab7<\/code> \u2014 \u043b\u0430\u0434\u044c\u044f \u0438\u0434\u0435\u0442 \u043d\u0430 b7 c \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438 a (\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0430 \u0441\u0435\u0434\u044c\u043c\u043e\u0438\u0306 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438 \u0441\u0442\u043e\u0438\u0442 \u0434\u0440\u0443\u0433\u0430\u044f \u043b\u0430\u0434\u044c\u044f). <\/p>\n<p>\u041f\u0440\u0438 \u0432\u0437\u044f\u0442\u0438\u0438 \u043f\u0435\u0448\u043a\u043e\u0438\u0306 \u0442\u0435\u043a\u0443\u0449\u0430\u044f \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c \u043f\u0435\u0448\u043a\u0438 \u0432 \u043d\u0430\u0448\u0435\u0438\u0306 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u043e\u0438\u0306 \u043d\u043e\u0442\u0430\u0446\u0438\u0438 \u043d\u0438\u043a\u043e\u0433\u0434\u0430 \u043d\u0435 \u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440: <\/p>\n<\/li>\n<li>\n<p><code>exd5<\/code> \u2014 \u043f\u0435\u0448\u043a\u0430 \u0441 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438 e \u0431\u044c\u0435\u0442 \u043d\u0430 d5. <\/p>\n<\/li>\n<\/ul>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0430\u0440\u0442\u0438\u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u043e\u043c \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0435 <code>chess.game<\/code>. \u0418\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0442\u043e \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u0430, \u0442\u043e \u0435\u0441\u0442\u044c \u0432\u0441\u0435 \u0445\u043e\u0434\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u044e\u0442\u0441\u044f \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u0438 \u043d\u0435 \u043d\u0430\u0440\u0443\u0448\u0430\u044e\u0442 \u043f\u0440\u0430\u0432\u0438\u043b \u0438\u0433\u0440\u044b. <\/p>\n<p>\u041d\u0430\u043f\u0438\u0448\u0438\u0442\u0435 \u0437\u0430\u043f\u0440\u043e\u0441, \u0432\u044b\u0432\u043e\u0434\u044f\u0449\u0438\u0438\u0306 \u043f\u043e\u0437\u0438\u0446\u0438\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0435\u0442 \u043d\u0430 \u0448\u0430\u0445\u043c\u0430\u0442\u043d\u043e\u0438\u0306 \u0434\u043e\u0441\u043a\u0435 \u043f\u043e\u0441\u043b\u0435 \u0432\u043e\u0441\u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0432\u0441\u0435\u0445 \u0445\u043e\u0434\u043e\u0432, \u0437\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0445 \u0432 \u0441\u043e\u043a\u0440\u0430\u0449\u0435\u043d\u043d\u043e\u0438\u0306 \u043d\u043e\u0442\u0430\u0446\u0438\u0438. \u0417\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0432 \u0442\u043e\u043c \u0436\u0435 \u0432\u0438\u0434\u0435, \u0447\u0442\u043e \u0438 \u0432 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0438\u0306 \u0437\u0430\u0434\u0430\u0447\u0435. <\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 <\/strong><\/p>\n<p>\u0414\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 <\/p>\n<pre><code class=\"pgsql\">SET chess.game='1. e4 e5 2. Bc4 Nc6 3. Qh5 Nf6 4. Qxf7#';<\/code><\/pre>\n<p>\u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438: <\/p>\n<pre><code> line |  chess ------+----------     8 | r.bqkb r     7 | pppp.Qpp     6 |  .n. n .     5 | . . p .     4 |  .B.P. .     3 | . . . .     2 | PPPP PPP     1 | RNB K NR (8 rows)<\/code><\/pre>\n<h3>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041f\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044e \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u0432 \u0437\u0430\u043f\u0438\u0441\u0438 \u043f\u0430\u0440\u0442\u0438\u0438 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0438 (\u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438, \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438, \u0438\u043b\u0438 \u043e\u0431\u0435\u0438\u0445 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442), \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u043d\u0435\u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e\u0441\u0442\u0438. \u0412\u043e\u0442 \u043f\u0440\u0438\u043c\u0435\u0440 \u043d\u0435\u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e\u0439 \u0437\u0430\u043f\u0438\u0441\u0438:<\/p>\n<pre><code>1. e4 e5 2. Nc3 d6 3. Ne2<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043d\u0430 \u043a\u043b\u0435\u0442\u043a\u0443 e2 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0439\u0442\u0438 \u043e\u0431\u0430 \u0431\u0435\u043b\u044b\u0445 \u043a\u043e\u043d\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0445\u043e\u0434 \u043e\u0431\u044f\u0437\u0430\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0443\u0436\u043d\u043e \u0443\u0442\u043e\u0447\u043d\u044f\u0442\u044c, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, <code>Nge2<\/code>.<\/p>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e \u043c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u0443\u0437\u043d\u0430\u0442\u044c, \u043a\u0430\u043a\u0430\u044f \u0438\u043c\u0435\u043d\u043d\u043e \u0444\u0438\u0433\u0443\u0440\u0430 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0443; \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043d\u0430\u0434\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0432\u0441\u0435 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0435 \u0445\u043e\u0434\u044b \u0438 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043f\u043e\u043b\u044f. \u042d\u0442\u043e \u0433\u043e\u0432\u043e\u0440\u0438\u0442 \u043d\u0430\u043c \u043e \u0442\u043e\u043c, \u0447\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0432 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u043c \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u043e\u043c \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438. \u0417\u0430\u0442\u043e \u0432\u0435\u0441\u044c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u043e\u0439 \u043a\u043e\u0434 \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0431\u0435\u0437 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0439.<\/p>\n<p>\u0421\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u0444\u0440\u0430\u0433\u043c\u0435\u043d\u0442 \u043f\u0430\u0440\u0442\u0438\u0438 \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0435\u0449\u0435 \u043e\u0434\u043d\u0443 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443:<\/p>\n<pre><code>1. a4 e5 2. Ra3 d5 3. Rh3<\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0439 \u0445\u043e\u0434 \u0437\u0430\u043f\u0438\u0441\u0430\u043d \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e, \u0445\u043e\u0442\u044f \u043a\u043b\u0435\u0442\u043a\u0430 h3 \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438 \u0441 \u043b\u0430\u0434\u044c\u0435\u0439 a3 \u0438 \u043d\u0430 \u043e\u0434\u043d\u043e\u0439 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438 \u0441 \u043b\u0430\u0434\u044c\u0435\u0439 h8. \u041d\u043e \u043b\u0430\u0434\u044c\u044f h \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0445\u043e\u0434 \u043d\u0430 h3, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u043f\u0435\u0440\u0435\u0434 \u043d\u0435\u0439 \u0441\u0442\u043e\u0438\u0442 \u043f\u0435\u0448\u043a\u0430. \u0422\u0435 \u043d\u0435\u043c\u043d\u043e\u0433\u0438\u0435 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u0434\u043e \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u0430, \u0440\u0435\u0448\u0438\u043b\u0438 \u043f\u043e\u0439\u0442\u0438 \u0442\u0430\u043a\u0438\u043c \u043f\u0443\u0442\u0435\u043c: 1) \u0432\u044b\u0431\u0440\u0430\u0442\u044c \u0432\u0441\u0435 \u043b\u0430\u0434\u044c\u0438 \u043d\u0430 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438 \u0438\u043b\u0438 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0438 \u0438 2) \u043e\u0442\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0442\u0435 \u043b\u0430\u0434\u044c\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0442\u0434\u0435\u043b\u0435\u043d\u044b \u043e\u0442 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0438 \u043a\u0430\u043a\u0438\u043c\u0438-\u043b\u0438\u0431\u043e \u0444\u0438\u0433\u0443\u0440\u0430\u043c\u0438. \u042f \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u044e \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u043f\u043e-\u0434\u0440\u0443\u0433\u043e\u043c\u0443: 1) \u0432\u044b\u0431\u0440\u0430\u0442\u044c <em>\u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0435<\/em> \u043a \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0435 \u0444\u0438\u0433\u0443\u0440\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0442\u043e\u044f\u0442 \u043d\u0430 \u0435\u0435 \u0433\u043e\u0440\u0438\u0437\u043e\u043d\u0442\u0430\u043b\u0438 \u0438\u043b\u0438 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438, \u0438 2) \u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0438\u0437 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u043e\u0433\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u0430\u0434\u044c\u0438. \u041a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u043f\u0440\u043e\u0449\u0435.<\/p>\n<p>\u0421 \u043b\u0430\u0434\u0435\u0439 \u0438 \u043d\u0430\u0447\u043d\u0435\u043c. \u0412\u043e\u0442 \u0447\u0442\u043e \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 <code>moves<\/code>, \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0432\u0448\u0438\u0441\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438:<\/p>\n<pre><code class=\"pgsql\">SET chess.game = '1. a2a4 e7e5 2. Ra3 d7d5 3. Rh3';  WITH RECURSIVE ... (   ... ) SELECT * FROM moves ORDER BY n;<\/code><\/pre>\n<pre><code> n | piece_from | v_from | h_from | piece_to | v_to | h_to  ---+------------+--------+--------+----------+------+------  1 | P          |      1 |      2 | P        |    1 |    4  2 | p          |      5 |      7 | p        |    5 |    5  3 | R          |        |        | R        |    1 |    3  4 | p          |      4 |      7 | p        |    4 |    5  5 | R          |        |        | R        |    8 |    3 (5 rows)<\/code><\/pre>\n<p>\u041f\u0435\u0448\u043a\u0430\u043c \u044f \u043f\u043e\u043a\u0430 \u043f\u043e\u0434\u0441\u0442\u0430\u0432\u0438\u043b \u043f\u043e\u043b\u043d\u0443\u044e \u043d\u043e\u0442\u0430\u0446\u0438\u044e, \u0430 \u0443 \u043b\u0430\u0434\u0435\u0439 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u043e \u043d\u0435 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u044b \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b <code>v_from<\/code> \u0438 <code>h_from<\/code>. \u0418\u0445-\u0442\u043e \u043d\u0430\u043c \u0438 \u043f\u0440\u0435\u0434\u0441\u0442\u043e\u0438\u0442 \u0432\u044b\u044f\u0441\u043d\u0438\u0442\u044c.<\/p>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0430 <code>game<\/code> \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u044f \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u044e \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 (<code>CROSS JOIN LATERAL<\/code>) \u0441 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u043c, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044e\u0442\u0441\u044f \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b; \u044d\u0442\u0438 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0437\u0430\u0442\u0435\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0432\u043c\u0435\u0441\u0442\u043e \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446\u044b <code>moves<\/code>. <code>LATERAL<\/code> \u043d\u0443\u0436\u0435\u043d, \u0447\u0442\u043e\u0431\u044b \u0438\u043c\u0435\u0442\u044c \u0432 \u044d\u0442\u043e\u043c \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0442\u043e\u043b\u0431\u0446\u0430\u043c <code>moves<\/code>.<\/p>\n<p>\u0412 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043f\u043e\u043a\u0430 \u0434\u0432\u0435 \u0447\u0430\u0441\u0442\u0438: \u043e\u0434\u043d\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0445\u043e\u0434 \u043b\u0430\u0434\u044c\u0435\u0439, \u0430 \u0432\u0442\u043e\u0440\u0430\u044f \u0441\u043b\u0443\u0436\u0438\u0442 \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u043e\u0439 \u0438 \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0438\u0437 <code>moves<\/code> \u0434\u043b\u044f \u0432\u0441\u0435\u0445 \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0438\u0433\u0443\u0440. \u0414\u0430\u043b\u044c\u0448\u0435 \u0432 \u044d\u0442\u043e\u0442 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0441\u0442\u0435\u043f\u0435\u043d\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0442\u044c \u043b\u043e\u0433\u0438\u043a\u0443 \u0434\u043b\u044f \u043e\u0441\u0442\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0444\u0438\u0433\u0443\u0440.<\/p>\n<p>\u041f\u043e \u043d\u0435\u0432\u0435\u0434\u043e\u043c\u044b\u043c \u043c\u043d\u0435 \u043f\u0440\u0438\u0447\u0438\u043d\u0430\u043c PostgreSQL \u0441\u0447\u0438\u0442\u0430\u0435\u0442, \u0447\u0442\u043e \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0435 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0440\u0430\u0437 (recursive reference to query must not appear more than once). \u041d\u0430\u043c \u043d\u0430\u0434\u043e \u0431\u043e\u043b\u044c\u0448\u0435, \u043d\u043e \u044d\u0442\u043e, \u043a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u043b\u0435\u0433\u043a\u043e \u043f\u0440\u0435\u043e\u0434\u043e\u043b\u0435\u0432\u0430\u0435\u0442\u0441\u044f \u043e\u0431\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0441\u044b\u043b\u043a\u0438 \u0432 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 <code>g<\/code>.<\/p>\n<p>\u0418\u0442\u0430\u043a, \u0432\u043e\u0442 \u0447\u0442\u043e \u0443 \u043d\u0430\u0441 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f:<\/p>\n<pre><code class=\"pgsql\">WITH RECURSIVE ... (   ... ), game(n,v,h,p) AS (   -- \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438   SELECT 1, v, h, p   FROM board   UNION ALL   -- \u0434\u0435\u043b\u0430\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0448\u0430\u0433   SELECT * FROM (     WITH g AS (       -- \u0432\u0441\u0435 \u0438\u0433\u0440\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435       SELECT * FROM game     ), pcs AS (       -- \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0438\u0433\u0443\u0440\u044b       SELECT * FROM g WHERE p != ' '     )     SELECT g.n+1, v, h,       CASE         WHEN v = v_to AND h = h_to THEN piece_to         -- \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0438\u0436\u0435         WHEN v = v_from2 AND h = h_from2 THEN ' '         ELSE p       END     FROM g       JOIN moves m ON m.n = g.n       -- \u0442\u0443\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b       CROSS JOIN LATERAL (         -- \u041b\u0430\u0434\u044c\u044f         SELECT v AS v_from2, h AS h_from2         FROM (           -- \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0430\u044f \u0444\u0438\u0433\u0443\u0440\u0430 \u043d\u0438\u0436\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.v = v_to AND pcs.h &lt; h_to           ORDER BY abs(pcs.h - h_to) LIMIT 1)           UNION ALL           -- \u0432\u044b\u0448\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.v = v_to AND pcs.h > h_to           ORDER BY abs(pcs.h - h_to) LIMIT 1)           UNION ALL           -- \u0441\u043b\u0435\u0432\u0430           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.h = h_to AND pcs.v &lt; v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043f\u0440\u0430\u0432\u0430           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.h = h_to AND pcs.v > v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)         )         WHERE p = piece_from -- \u0438\u0437 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0445 \u0444\u0438\u0433\u0443\u0440 \u0431\u0435\u0440\u0435\u043c \u043b\u0430\u0434\u044c\u0438           AND piece_from IN ('R','r')           -- \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b           AND (v_from IS NULL OR v = v_from)           AND (h_from IS NULL OR h = h_from)         UNION ALL         -- \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0438\u0433\u0443\u0440\u044b         -- \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f \u0437\u0430\u0433\u043b\u0443\u0448\u043a\u0430: \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u043d\u0430 \u043f\u043e\u043b\u043d\u0443\u044e \u043d\u043e\u0442\u0430\u0446\u0438\u044e         SELECT v_from, h_from         WHERE piece_from NOT IN ('R','r')       )   ) ), ... ...<\/code><\/pre>\n<pre><code> line |  chess    ------+----------     8 | rnbqkbnr     7 | ppp .ppp     6 |  . . . .     5 | . .pp .      4 | P. . . .     3 | . . . .R     2 |  PPPPPPP     1 | .NBQKBNR (8 rows)<\/code><\/pre>\n<p>\u041d\u0430 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u0445\u043e\u0434\u0443 \u0432 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u0431\u044b\u043b\u0438 \u0432\u044b\u0431\u0440\u0430\u043d\u044b \u0442\u0440\u0438 \u0444\u0438\u0433\u0443\u0440\u044b, \u0431\u043b\u0438\u0436\u0430\u0439\u0448\u0438\u0435 \u043a \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0435 h3: \u043f\u0435\u0448\u043a\u0438 h7 \u0438 h2 \u0438 \u043b\u0430\u0434\u044c\u044f a3. \u041f\u0435\u0448\u043a\u0438 \u043c\u044b \u043e\u0442\u0431\u0440\u043e\u0441\u0438\u043b\u0438, \u0430 \u043b\u0430\u0434\u044c\u044f \u043e\u0441\u0442\u0430\u043b\u0430\u0441\u044c \u0438 \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u043b\u0430 \u0445\u043e\u0434.<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0430\u0440\u0442\u0438\u0438 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e\u0439 \u0438\u043b\u0438 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u0439, \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441 \u043c\u043e\u0436\u0435\u0442 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a \u0438\u043b\u0438 \u043d\u0435 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0438 \u043e\u0434\u043d\u043e\u0439. \u042d\u0442\u043e \u0432\u0441\u0435 \u0441\u043b\u043e\u043c\u0430\u0435\u0442, \u043d\u043e, \u043a \u0441\u0447\u0430\u0441\u0442\u044c\u044e, \u043f\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044e \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430\u043c \u043d\u0435 \u043d\u0430\u0434\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438.<\/p>\n<p>\u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u043d\u0430\u0447\u0430\u043b\u0430 \u0432\u044b\u0431\u0438\u0440\u0430\u044e\u0442\u0441\u044f \u0432\u0441\u0435 \u0444\u0438\u0433\u0443\u0440\u044b, \u0440\u0430\u0432\u043d\u044b\u0435 \u0446\u0435\u043b\u0435\u0432\u043e\u0439, \u0430 \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u043f\u0440\u0435\u043f\u044f\u0442\u0441\u0442\u0432\u0438\u0439 \u0434\u043b\u044f \u0445\u043e\u0434\u0430, \u0437\u0434\u0435\u0441\u044c \u0432\u0441\u044f \u043b\u043e\u0433\u0438\u043a\u0430, \u043a\u0430\u0441\u0430\u044e\u0449\u0430\u044f\u0441\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0444\u0438\u0433\u0443\u0440\u044b, \u043d\u0435 \u0440\u0430\u0437\u043c\u0430\u0437\u0430\u043d\u0430 \u043f\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0443, \u0430 \u043b\u043e\u043a\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u0432 \u043e\u0434\u043d\u043e\u043c \u043c\u0435\u0441\u0442\u0435. \u042d\u0442\u043e \u043f\u043e\u043b\u0435\u0437\u043d\u043e\u0435 \u0434\u043b\u044f \u043e\u0442\u043b\u0430\u0434\u043a\u0438 \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u043e.<\/p>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u043c\u043e\u0436\u043d\u043e \u0438 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c\u0441\u044f, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u0444\u0438\u0433\u0443\u0440\u044b \u043f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u043d\u0435 \u0442\u0430\u043a \u0443\u0436 \u0438 \u0441\u043b\u043e\u0436\u043d\u043e (\u0445\u043e\u0442\u044f \u0438 \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u043e\u0432\u0430\u0442\u043e). \u0421\u0434\u0435\u043b\u0430\u044e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043e\u043a \u043d\u0430 \u0441\u043b\u0443\u0447\u0430\u0439, \u0435\u0441\u043b\u0438 \u0437\u0430\u0445\u043e\u0442\u0438\u0442\u0435 \u043f\u043e\u043f\u0440\u043e\u0431\u043e\u0432\u0430\u0442\u044c \u0441\u0430\u043c\u0438.<\/p>\n<p>\u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043d\u0430\u0434\u043e \u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e \u0438\u0437-\u0437\u0430 \u043f\u0435\u0448\u0435\u043a \u043d\u0430 \u0434\u043e\u0441\u043a\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u044f\u0432\u0438\u0442\u044c\u0441\u044f \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043b\u044e\u0431\u044b\u0445 \u0444\u0438\u0433\u0443\u0440 (\u043a\u0440\u043e\u043c\u0435 \u043a\u043e\u0440\u043e\u043b\u044f). \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u0432\u0430 \u0444\u0435\u0440\u0437\u044f \u0438\u043b\u0438 \u0434\u0432\u0430 \u0431\u0435\u043b\u043e\u043f\u043e\u043b\u044c\u043d\u044b\u0445 \u0441\u043b\u043e\u043d\u0430. \u0422\u0430\u043a \u0447\u0442\u043e \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0443\u043d\u0438\u043a\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f.<\/p>\n<p>\u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u043a\u043e\u043d\u044c \u00ab\u043f\u0435\u0440\u0435\u043f\u0440\u044b\u0433\u0438\u0432\u0430\u0435\u0442\u00bb \u0447\u0435\u0440\u0435\u0437 \u0444\u0438\u0433\u0443\u0440\u044b, \u0447\u0442\u043e \u0443\u043f\u0440\u043e\u0449\u0430\u0435\u0442 \u0437\u0430\u0434\u0430\u0447\u0443 (\u0445\u043e\u0442\u044f \u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b).<\/p>\n<p>\u0412-\u0442\u0440\u0435\u0442\u044c\u0438\u0445, \u043d\u0435 \u043d\u0430\u0434\u043e \u0437\u0430\u0431\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u043e <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%92%D0%B7%D1%8F%D1%82%D0%B8%D0%B5_%D0%BD%D0%B0_%D0%BF%D1%80%D0%BE%D1%85%D0%BE%D0%B4%D0%B5\">\u0432\u0437\u044f\u0442\u0438\u0435 \u043d\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0435<\/a> (\u043d\u0438 \u043e\u0434\u0438\u043d \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a \u0435\u0433\u043e \u043d\u0435 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b, \u0445\u043e\u0442\u044f \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430\u043c\u0435\u043a \u0431\u044b\u043b \u0434\u0430\u043d). \u0422\u0443\u0442, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e \u0445\u043e\u0434\u0430, \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e\u0442 \u0442\u0440\u0438 \u043a\u043b\u0435\u0442\u043a\u0438, \u0447\u0442\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043e\u0441\u043e\u0431\u043e\u0439 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"pgsql\">WITH RECURSIVE rawmoves(n,color,move) AS (   -- \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0445\u043e\u0434\u044b \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0446\u0432\u0435\u0442   SELECT row_number() over() * 2,       CASE WHEN row_number() over() % 2 = 0 THEN 'B' ELSE 'W' END,      move[1]   FROM regexp_matches(        coalesce(translate(current_setting('chess.game',true),'x+#',''),'') || ' ',        '([a-h1-8rbnqkRBNQKO-]+) ', 'g'      ) move ), castling(color,move,n,newmove) AS (   VALUES -- \u0445\u043e\u0434\u044b \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a     ('W',   'O-O', 0, 'Rh1f1'),     ('W',   'O-O', 1, 'Ke1g1'),     ('W', 'O-O-O', 0, 'Ra1d1'),     ('W', 'O-O-O', 1, 'Ke1c1'),     ('B',   'O-O', 0, 'Rh8f8'),     ('B',   'O-O', 1, 'Ke8g8'),     ('B', 'O-O-O', 0, 'Ra8d8'),     ('B', 'O-O-O', 1, 'Ke8c8') ), castlingmoves(n,color,move) AS (   -- \u0437\u0430\u043c\u0435\u043d\u044f\u0435\u043c \u0440\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0443 \u043d\u0430 \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0445\u043e\u0434\u044b   SELECT r.n+coalesce(c.n,0), r.color, coalesce(c.newmove,r.move)   FROM rawmoves r     LEFT JOIN castling c ON c.color = r.color AND c.move = r.move ), components(n,color,piece_from,v_from,h_from,piece_to,v_to,h_to) AS (   -- \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u043c \u043a\u0430\u0436\u0434\u044b\u0439 \u0445\u043e\u0434 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b   SELECT n, color, coalesce(nullif(m[1],''),'P'),      nullif(m[2],''), nullif(m[3],''), nullif(m[6],''), m[4], m[5]   FROM (     SELECT n, color,       regexp_matches(move,'([RBNQK]?)([a-h]?)([1-8]?)([a-h])([1-8])([RBNQ])?') m     FROM castlingmoves   ) ), moves(n,piece_from,v_from,h_from,piece_to,v_to,h_to) AS (   SELECT n,     CASE WHEN color = 'B' THEN lower(piece_from) ELSE piece_from END,     v_from, h_from,     CASE WHEN color = 'B' THEN lower(piece_to) ELSE piece_to END,     v_to, h_to   FROM (     SELECT row_number() OVER (ORDER BY n) AS n,       color,       piece_from,       ascii(v_from) - ascii('a') + 1 AS v_from,       nullif(h_from,'')::integer AS h_from,       coalesce(piece_to,         CASE           WHEN piece_from = 'P' AND h_to IN ('1','8') THEN 'Q'           ELSE piece_from         END) AS piece_to,       ascii(v_to) - ascii('a') + 1 AS v_to,       nullif(h_to,'')::integer AS h_to     FROM components   ) ), board(v,h,p) AS (   -- \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u0430\u044f \u043f\u043e\u0437\u0438\u0446\u0438\u044f (\u0432\u0441\u0435 \u043a\u043b\u0435\u0442\u043a\u0438)   VALUES   (1,1,'R'),(2,1,'N'),(3,1,'B'),(4,1,'Q'),(5,1,'K'),(6,1,'B'),(7,1,'N'),(8,1,'R'),   (1,2,'P'),(2,2,'P'),(3,2,'P'),(4,2,'P'),(5,2,'P'),(6,2,'P'),(7,2,'P'),(8,2,'P'),   (1,7,'p'),(2,7,'p'),(3,7,'p'),(4,7,'p'),(5,7,'p'),(6,7,'p'),(7,7,'p'),(8,7,'p'),   (1,8,'r'),(2,8,'n'),(3,8,'b'),(4,8,'q'),(5,8,'k'),(6,8,'b'),(7,8,'n'),(8,8,'r')   UNION ALL   SELECT v, h, ' ' FROM generate_series(1,8) v, generate_series(3,6) h ), game(n,v,h,p) AS (   -- \u043d\u0430\u0447\u0438\u043d\u0430\u0435\u043c \u0441 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0439 \u043f\u043e\u0437\u0438\u0446\u0438\u0438   SELECT 1, v, h, p   FROM board   UNION ALL   -- \u0434\u0435\u043b\u0430\u0435\u043c \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u043e\u0439 \u0448\u0430\u0433   SELECT * FROM (     WITH g AS (       -- \u0432\u0441\u0435 \u0438\u0433\u0440\u043e\u0432\u043e\u0435 \u043f\u043e\u043b\u0435       SELECT * FROM game     ), pcs AS (       -- \u0442\u043e\u043b\u044c\u043a\u043e \u0444\u0438\u0433\u0443\u0440\u044b       SELECT * FROM g WHERE p != ' '     )     SELECT g.n+1, v, h,       CASE         WHEN v = v_to AND h = h_to THEN piece_to         -- \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b \u0431\u0435\u0440\u0435\u043c \u0438\u0437 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043d\u0438\u0436\u0435         WHEN (v = v_from2 OR (enpass AND v = v_to)) AND h = h_from2 THEN ' '         ELSE p       END     FROM g       JOIN moves m ON m.n = g.n       -- \u0442\u0443\u0442 \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b       CROSS JOIN LATERAL (         ---- \u041f\u0435\u0448\u043a\u0430 - \u0432\u0437\u044f\u0442\u0438\u0435         SELECT pcs.v AS v_from2, pcs.h AS h_from2,           -- \u043f\u0440\u0438\u0437\u043d\u0430\u043a \u0432\u0437\u044f\u0442\u0438\u044f \u043d\u0430 \u043f\u0440\u043e\u0445\u043e\u0434\u0435 - \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0438\u0435 \u0444\u0438\u0433\u0443\u0440\u044b \u0432 \u0446\u0435\u043b\u0435\u0432\u043e\u0439 \u043a\u043b\u0435\u0442\u043a\u0435           NOT EXISTS (             SELECT NULL FROM pcs WHERE h = h_to AND v = v_to           ) AS enpass         FROM pcs         WHERE pcs.p = piece_from           AND piece_from IN ('P','p')           -- \u043f\u0440\u0438 \u0432\u0437\u044f\u0442\u0438\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043e\u0431\u0435 \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438, \u0438 \u043e\u043d\u0438 \u043d\u0435 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442           AND v_from != v_to           AND pcs.v = v_from           -- \u043d\u0430\u0438\u0441\u043a\u043e\u0441\u043e\u043a           AND pcs.h = h_to + CASE                 WHEN piece_from = 'p' THEN +1 ELSE -1               END         UNION ALL         ---- \u041f\u0435\u0448\u043a\u0430 - \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0445\u043e\u0434         (SELECT pcs.v, pcs.h, false         FROM pcs         WHERE pcs.p = piece_from           -- \u0442\u043e\u043b\u044c\u043a\u043e \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u044c           AND pcs.v = v_to           -- \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0446\u0432\u0435\u0442\u0430 \u043f\u0435\u0448\u043a\u0438           AND ( (piece_from = 'p' AND pcs.h > h_to)                 OR                 (piece_from = 'P' AND pcs.h &lt; h_to) )           -- \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b           AND (v_from IS NULL OR pcs.v = v_from)           AND (h_from IS NULL OR pcs.h = h_from)           -- \u0432\u0435\u0440\u0442\u0438\u043a\u0430\u043b\u0438 \u0441\u043e\u0432\u043f\u0430\u0434\u0430\u044e\u0442, \u0435\u0441\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b \u043e\u0431\u0435           AND (v_from IS NULL OR v_from = v_to)         ORDER BY abs(h_to - pcs.h) LIMIT 1)         UNION ALL         ---- \u041b\u0430\u0434\u044c\u044f         SELECT v, h, false         FROM (           -- \u043d\u0438\u0436\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.v = v_to AND pcs.h &lt; h_to           ORDER BY abs(pcs.h - h_to) LIMIT 1)           UNION ALL           -- \u0432\u044b\u0448\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.v = v_to AND pcs.h > h_to           ORDER BY abs(pcs.h - h_to) LIMIT 1)           UNION ALL           -- \u0441\u043b\u0435\u0432\u0430           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.h = h_to AND pcs.v &lt; v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043f\u0440\u0430\u0432\u0430           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.h = h_to AND pcs.v > v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)         )         WHERE p = piece_from           AND piece_from IN ('R','r')           -- \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b           AND (v_from IS NULL OR v = v_from)           AND (h_from IS NULL OR h = h_from)         UNION ALL         ---- \u0421\u043b\u043e\u043d         SELECT v, h, false         FROM (           -- \u0441\u043b\u0435\u0432\u0430 \u043d\u0438\u0436\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE abs(pcs.v - v_to) = abs(pcs.h - h_to)             AND pcs.h &lt; h_to AND pcs.v &lt; v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043b\u0435\u0432\u0430 \u0432\u044b\u0448\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE abs(pcs.v - v_to) = abs(pcs.h - h_to)             AND pcs.h &lt; h_to AND pcs.v > v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0438\u0436\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE abs(pcs.v - v_to) = abs(pcs.h - h_to)             AND pcs.h > h_to AND pcs.v &lt; v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043f\u0440\u0430\u0432\u0430 \u0432\u044b\u0448\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE abs(pcs.v - v_to) = abs(pcs.h - h_to)             AND pcs.h > h_to AND pcs.v > v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)         )         WHERE p = piece_from           AND piece_from IN ('B','b')           -- \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b           AND (v_from IS NULL OR v = v_from)           AND (h_from IS NULL OR h = h_from)         UNION ALL         ---- \u0424\u0435\u0440\u0437\u044c         SELECT v, h, false         FROM (           -- \u043d\u0438\u0436\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.v = v_to AND pcs.h &lt; h_to           ORDER BY abs(pcs.h - h_to) LIMIT 1)           UNION ALL           -- \u0432\u044b\u0448\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.v = v_to AND pcs.h > h_to           ORDER BY abs(pcs.h - h_to) LIMIT 1)           UNION ALL           -- \u0441\u043b\u0435\u0432\u0430           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.h = h_to AND pcs.v &lt; v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043f\u0440\u0430\u0432\u0430           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE pcs.h = h_to AND pcs.v > v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043b\u0435\u0432\u0430 \u043d\u0438\u0436\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE abs(pcs.v - v_to) = abs(pcs.h - h_to)             AND pcs.h &lt; h_to AND pcs.v &lt; v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043b\u0435\u0432\u0430 \u0432\u044b\u0448\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE abs(pcs.v - v_to) = abs(pcs.h - h_to)             AND pcs.h &lt; h_to AND pcs.v > v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043f\u0440\u0430\u0432\u0430 \u043d\u0438\u0436\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE abs(pcs.v - v_to) = abs(pcs.h - h_to)             AND pcs.h > h_to AND pcs.v &lt; v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)           UNION ALL           -- \u0441\u043f\u0440\u0430\u0432\u0430 \u0432\u044b\u0448\u0435           (SELECT pcs.p, pcs.v, pcs.h FROM pcs           WHERE abs(pcs.v - v_to) = abs(pcs.h - h_to)             AND pcs.h > h_to AND pcs.v > v_to           ORDER BY abs(pcs.v - v_to) LIMIT 1)         )         WHERE p = piece_from           AND piece_from IN ('Q','q')           -- \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b           AND (v_from IS NULL OR v = v_from)           AND (h_from IS NULL OR h = h_from)         UNION ALL         ---- \u041a\u043e\u043d\u044c         (SELECT pcs.v, pcs.h, false         FROM pcs         WHERE pcs.p = piece_from           AND piece_from IN ('N','n')           AND ( (abs(pcs.v - v_to) = 1 AND abs(pcs.h - h_to) = 2)              OR (abs(pcs.v - v_to) = 2 AND abs(pcs.h - h_to) = 1) )           -- \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0435\u043c \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u043a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u044b           AND (v_from IS NULL OR pcs.v = v_from)           AND (h_from IS NULL OR pcs.h = h_from)         )         UNION ALL         ---- \u041a\u043e\u0440\u043e\u043b\u044c (\u0432\u0441\u0435\u0433\u0434\u0430 \u043e\u0434\u0438\u043d)         SELECT pcs.v, pcs.h, false         FROM pcs         WHERE pcs.p = piece_from           AND piece_from in ('K','k')       )   ) ), last_board AS (   -- \u0431\u0435\u0440\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u044e   SELECT * FROM game WHERE n = (SELECT max(n) FROM game) ) SELECT h.h AS line,   string_agg(     CASE WHEN b.p = ' ' AND (v.v+h.h) % 2 = 0 THEN '.' ELSE b.p END,     '' ORDER BY v.v   ) AS chess FROM generate_series(1,8) h(h)   CROSS JOIN generate_series(1,8) v(v)   LEFT JOIN last_board b ON b.h = h.h AND b.v = v.v GROUP BY h.h ORDER BY h.h DESC;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u0438\u0434\u0443\u043c\u0430\u0435\u0442\u0435, \u043a\u0430\u043a \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0431\u043e\u043b\u0435\u0435 \u043a\u043e\u043c\u043f\u0430\u043a\u0442\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441, \u0431\u0443\u0434\u0443 \u043f\u0440\u0438\u0437\u043d\u0430\u0442\u0435\u043b\u0435\u043d \u0437\u0430 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439.<\/p>\n<h4>\u041d\u0435 \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0442\u0430\u043a<\/h4>\n<ul>\n<li>\n<p>\u041d\u0435\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f (\u043c\u0430\u043d\u0438\u043f\u0443\u043b\u0438\u0440\u0443\u044e\u0449\u0438\u0435 JSON-\u0430\u043c\u0438 \u0438\u043b\u0438 \u0441\u0442\u0440\u043e\u043a\u0430\u043c\u0438) \u043e\u043a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0441\u043b\u043e\u0436\u043d\u0435\u0435 \u043f\u0440\u0438\u0441\u043f\u043e\u0441\u043e\u0431\u0438\u0442\u044c \u043f\u043e\u0434 \u0438\u0437\u043c\u0435\u043d\u0438\u0432\u0448\u0438\u0435\u0441\u044f \u0443\u0441\u043b\u043e\u0432\u0438\u044f. \u0415\u0441\u043b\u0438 \u0441\u0447\u0435\u0442 \u0441\u0442\u0440\u043e\u043a\u0430\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438\u0434\u0435\u0442 \u0443\u0436\u0435 \u043d\u0430 \u0442\u044b\u0441\u044f\u0447\u0438 \u2014 \u0434\u0435\u043b\u043e \u043d\u0435\u043b\u0430\u0434\u043d\u043e, \u043f\u043e\u0440\u0430 \u043d\u0430\u0441\u0442\u043e\u0440\u043e\u0436\u0438\u0442\u044c\u0441\u044f.<\/p>\n<\/li>\n<li>\n<p>\u042f \u0438 \u0440\u0430\u043d\u044c\u0448\u0435 \u043f\u043e\u0434\u043e\u0437\u0440\u0435\u0432\u0430\u043b, \u0447\u0442\u043e \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 (\u0445\u043e\u0442\u044f \u0447\u0435\u0433\u043e \u0443\u0436 \u0442\u0430\u043c, \u043c\u043d\u043e\u0433\u0438\u0435) \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0438 \u043f\u044b\u0442\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u043e\u0441\u043a\u043e\u0447\u0438\u0442\u044c \u043d\u0430 ChatGPT, \u043f\u0440\u0438\u0441\u044b\u043b\u0430\u044f \u043e\u0442\u043a\u0440\u043e\u0432\u0435\u043d\u043d\u043e \u043d\u0435\u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043a\u043e\u0434. \u041d\u043e \u0432 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u044f \u0432 \u044d\u0442\u043e\u043c \u0430\u0431\u0441\u043e\u043b\u044e\u0442\u043d\u043e \u0443\u0432\u0435\u0440\u0435\u043d: \u0432\u0435\u0434\u044c \u043d\u0438 \u043e\u0434\u043d\u043e\u043c\u0443 \u0436\u0438\u0432\u043e\u043c\u0443 \u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0443 \u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e \u0431\u044b \u0432 \u0433\u043e\u043b\u043e\u0432\u0443 \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0432 \u0437\u0430\u043f\u0440\u043e\u0441 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 <code>deeds<\/code> \u0438\u0437 \u043f\u043e\u0437\u0430\u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438. \u0410 \u043a\u043e\u0435-\u043a\u0442\u043e \u043e\u0431\u043b\u0435\u043d\u0438\u043b\u0441\u044f \u0434\u043e \u0442\u0430\u043a\u043e\u0439 \u0441\u0442\u0435\u043f\u0435\u043d\u0438, \u0447\u0442\u043e \u0434\u0430\u0436\u0435 \u043d\u0435 \u0441\u0442\u0430\u043b \u0443\u0434\u0430\u043b\u044f\u0442\u044c \u0432\u0432\u043e\u0434\u043d\u044b\u0435 \u0441\u043b\u043e\u0432\u0430. MySQL, \u041a\u0430\u0440\u043b!<\/p>\n<\/li>\n<\/ul>\n<blockquote>\n<p>\u0414\u043b\u044f \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0438 \u043d\u0430 SQL \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434:<br \/>&#8230;<br \/>\u042d\u0442\u043e\u0442 SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u0441\u043e\u0437\u0434\u0430\u0435\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0448\u0430\u0445\u043c\u0430\u0442\u043d\u043e\u0439 \u0434\u043e\u0441\u043a\u0438 \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0435\u0435 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c. \u0417\u0430\u0442\u0435\u043c \u043e\u043d \u0440\u0430\u0437\u0431\u0438\u0432\u0430\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u044c \u043f\u0430\u0440\u0442\u0438\u0438 \u043d\u0430 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0445\u043e\u0434\u044b \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0435\u0442 \u043a\u0430\u0436\u0434\u044b\u0439 \u0445\u043e\u0434 \u043a \u0434\u043e\u0441\u043a\u0435. \u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u043e\u043d \u0432\u044b\u0432\u043e\u0434\u0438\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0434\u043e\u0441\u043a\u0438 \u0432 \u0432\u0438\u0434\u0435 \u0448\u0430\u0445\u043c\u0430\u0442\u043d\u043e\u0439 \u0434\u043e\u0441\u043a\u0438. \u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u044d\u0442\u043e\u0442 SQL-\u0437\u0430\u043f\u0440\u043e\u0441 \u0432 \u0441\u0440\u0435\u0434\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0430\u0437\u0430\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 MySQL \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u043e\u0439 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0435\u0439 SQL \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0434\u043b\u044f \u0432\u0430\u0448\u0435\u0433\u043e \u043f\u0440\u0438\u043c\u0435\u0440\u0430.<\/p>\n<\/blockquote>\n<h2>\u0417\u0430\u0434\u0430\u0447\u0430 5. \u0425\u0430\u043d\u043e\u0439\u0441\u043a\u0430\u044f \u0431\u0430\u0448\u043d\u044f<\/h2>\n<h3>\u0423\u0441\u043b\u043e\u0432\u0438\u0435<\/h3>\n<p>\u0421\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0438\u0306 \u043b\u0435\u0433\u0435\u043d\u0434\u0435, \u043f\u0440\u043e\u0432\u0438\u043d\u0438\u0432\u0448\u0438\u0435\u0441\u044f \u043f\u0435\u0440\u0435\u0434 \u0411\u0440\u0430\u0445\u043c\u043e\u0438\u0306 \u043c\u043e\u043d\u0430\u0445\u0438 \u0434\u043e\u043b\u0436\u043d\u044b \u0432 \u043d\u0430\u043a\u0430\u0437\u0430\u043d\u0438\u0435 \u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0434\u0438\u0441\u043a\u0438 \u0440\u0430\u0437\u043d\u043e\u0433\u043e \u0434\u0438\u0430\u043c\u0435\u0442\u0440\u0430 \u0441\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f \u043d\u0430 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u043c\u0435\u043d\u044c\u0448\u0438\u0435 \u0434\u0438\u0441\u043a\u0438 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u043e\u043a\u043e\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445. <\/p>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e \u043d\u0430\u043f\u043b\u044b\u0432 \u0442\u0443\u0440\u0438\u0441\u0442\u043e\u0432 \u043e\u0447\u0435\u043d\u044c \u043c\u0435\u0448\u0430\u043b \u043c\u043e\u043d\u0430\u0445\u0430\u043c \u0441\u043f\u043e\u043a\u043e\u0438\u0306\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043d\u0430\u0434 \u043f\u0440\u0438\u0431\u043b\u0438\u0436\u0435\u043d\u0438\u0435\u043c \u043a\u043e\u043d\u0446\u0430 \u0441\u0432\u0435\u0442\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0438\u0306 \u043d\u0430\u0441\u0442\u0443\u043f\u0438\u0442, \u043a\u043e\u0433\u0434\u0430 \u0432\u0441\u0435 64 \u0434\u0438\u0441\u043a\u0430 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0441 \u043e\u0434\u043d\u043e\u0433\u043e \u0438\u0437 \u0441\u0442\u0435\u0440\u0436\u043d\u0435\u0438\u0306 \u043d\u0430 \u043a\u0430\u043a\u043e\u0438\u0306-\u043b\u0438\u0431\u043e \u0434\u0440\u0443\u0433\u043e\u0438\u0306. \u0422\u043e\u0433\u0434\u0430 \u043c\u043e\u043d\u0430\u0445\u0438 \u0440\u0435\u0448\u0438\u043b\u0438 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0441\u0432\u043e\u044e \u0437\u0430\u0434\u0430\u0447\u0443 \u0432 \u043e\u043d\u043b\u0430\u0438\u0306\u043d, \u0447\u0442\u043e\u0431\u044b \u043a\u0430\u0436\u0434\u044b\u0438\u0306 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0438\u0306 \u043c\u043e\u0433 \u043f\u043e\u0443\u0447\u0430\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0432 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0435. \u0418\u0437 \u043a\u043b\u0438\u0435\u043d\u0442\u0441\u043a\u043e\u0438\u0306 \u0447\u0430\u0441\u0442\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u0433\u043e \u0438\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u0430\u044f \u0445\u0440\u0430\u043d\u0438\u043c\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f: <\/p>\n<pre><code class=\"pgsql\">FUNCTION move(rod_from integer, rod_to integer) RETURNS integer;<\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442 \u043d\u043e\u043c\u0435\u0440\u0430 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0438 \u0446\u0435\u043b\u0435\u0432\u043e\u0433\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u0435\u0438\u0306 \u0438 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0432\u0435\u0440\u0445\u043d\u0438\u0438\u0306 \u0434\u0438\u0441\u043a \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f \u043d\u0430 \u0446\u0435\u043b\u0435\u0432\u043e\u0438\u0306, \u0435\u0441\u043b\u0438 \u044d\u0442\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e. \u0417\u0430\u043f\u0440\u0435\u0449\u0435\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0434\u0438\u0441\u043a \u043d\u0430 \u0434\u0438\u0441\u043a \u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e \u0434\u0438\u0430\u043c\u0435\u0442\u0440\u0430, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0441\u043d\u0438\u043c\u0430\u0442\u044c \u0434\u0438\u0441\u043a \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u0435\u0433\u043e \u043d\u0430 \u0442\u043e\u0442 \u0436\u0435 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c. <\/p>\n<p>\u0421\u0442\u0435\u0440\u0436\u043d\u0438 \u043f\u0440\u043e\u043d\u0443\u043c\u0435\u0440\u043e\u0432\u0430\u043d\u044b \u043e\u0442 1 \u0434\u043e 64. \u041e\u0431\u044b\u0447\u043d\u043e \u0434\u0443\u043c\u0430\u044e\u0442, \u0447\u0442\u043e \u0411\u0440\u0430\u0445\u043c\u0430 \u0441\u043e\u0437\u0434\u0430\u043b \u0432\u0441\u0435\u0433\u043e \u0442\u0440\u0438 \u0430\u043b\u043c\u0430\u0437\u043d\u044b\u0445 \u0441\u0442\u0435\u0440\u0436\u043d\u044f, \u043d\u043e \u043c\u043e\u043d\u0430\u0445\u0438 \u0440\u0435\u0448\u0438\u043b\u0438 \u0432\u043e\u0441\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438\u0441\u0442\u043e\u0440\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0441\u0442\u044c: \u043e\u043d\u0438 \u0445\u043e\u0440\u043e\u0448\u043e \u043f\u043e\u043c\u043d\u044f\u0442, \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u043e\u0438\u0306 \u0436\u0435 \u043d\u043e\u0447\u044c\u044e \u043f\u043e\u0447\u0442\u0438 \u0432\u0441\u0435 \u0441\u0442\u0435\u0440\u0436\u043d\u0438 \u0438\u0441\u0447\u0435\u0437\u043b\u0438 \u0432 \u043d\u0435\u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u043c \u043d\u0430\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0438. <\/p>\n<p>\u0418\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0442\u043e \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0438\u0306 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043d\u043e \u0432 \u043d\u0435\u0435 \u043c\u043e\u0433\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u0438 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b (\u043c\u043e\u043d\u0430\u0445\u0438 \u043d\u0435 \u0441\u0438\u043b\u044c\u043d\u044b \u0432\u043e \u0444\u0440\u043e\u043d\u0442\u0435\u043d\u0434\u0435). <\/p>\n<p>\u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u0441\u043f\u0435\u0445\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u043e\u043c\u0435\u0440 \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u043e\u0433\u043e \u0434\u0438\u0441\u043a\u0430 (\u0434\u0438\u0441\u043a\u0438 \u043f\u0440\u043e\u043d\u0443\u043c\u0435\u0440\u043e\u0432\u0430\u043d\u044b \u043e\u0442 1 \u0434\u043e 64 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435 \u0432\u043e\u0437\u0440\u0430\u0441\u0442\u0430\u043d\u0438\u044f \u0434\u0438\u0430\u043c\u0435\u0442\u0440\u0430). \u0415\u0441\u043b\u0438 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u043d\u0435\u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c\u0441\u044f \u043e\u0448\u0438\u0431\u043a\u043e\u0438\u0306 (\u043b\u044e\u0431\u043e\u0438\u0306). <\/p>\n<p>\u0421\u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u0443\u0438\u0306\u0442\u0435 \u0441\u0445\u0435\u043c\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0438\u0306\u0442\u0435 \u0434\u043b\u044f \u043d\u0435\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <code>move<\/code> <em>\u043d\u0430 \u044f\u0437\u044b\u043a\u0435 SQL <\/em>\u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0445. \u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0434\u043e\u043b\u0436\u043d\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c SQL-\u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u043d\u043e\u0438\u0306 \u043d\u0430\u0447\u0430\u043b\u044c\u043d\u044b\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0442\u0430\u043a, \u0447\u0442\u043e\u0431\u044b \u0432\u0441\u0435 64 \u0434\u0438\u0441\u043a\u0430 \u043d\u0430\u0445\u043e\u0434\u0438\u043b\u0438\u0441\u044c \u043d\u0430 \u043f\u0435\u0440\u0432\u043e\u043c \u0441\u0442\u0435\u0440\u0436\u043d\u0435. <\/p>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c, \u0447\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c\u0441\u044f \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438\u0306. \u0421\u0440\u0435\u0434\u0438 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0445 \u0440\u0435\u0448\u0435\u043d\u0438\u0438\u0306 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u0430\u043b\u043b\u044b \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435; \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u044e\u0449\u0438\u0435 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435, \u043d\u0435 \u043f\u043e\u043b\u0443\u0447\u0430\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0431\u0430\u043b\u043b\u043e\u0432. <\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440<\/h4>\n<p>\u0415\u0441\u043b\u0438 \u0432\u0441\u0435 \u0434\u0438\u0441\u043a\u0438 \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u043d\u0430 \u0441\u0442\u0435\u0440\u0436\u043d\u0435 1 (\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e\u0435 \u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435), \u0442\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0438\u0306 \u0432\u044b\u0437\u043e\u0432: <\/p>\n<pre><code class=\"pgsql\">SELECT move(1,2);<\/code><\/pre>\n<p>\u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u0438\u0441\u043a 1 \u0441\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f 1 \u043d\u0430 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c 2 \u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c <\/p>\n<pre><code> move  ------      1 (1 rows)<\/code><\/pre>\n<p>\u0417\u0430\u0442\u0435\u043c \u0432\u044b\u0437\u043e\u0432 <\/p>\n<pre><code class=\"pgsql\">SELECT move(1,3);<\/code><\/pre>\n<p>\u0434\u043e\u043b\u0436\u0435\u043d \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u0438\u0441\u043a 2 \u0441\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f 1 \u043d\u0430 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c 3 \u0438 \u0432\u0435\u0440\u043d\u0443\u0442\u044c <\/p>\n<pre><code> move  ------      2 (1 rows)<\/code><\/pre>\n<p>\u041f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u0432\u044b\u0437\u043e\u0432 <\/p>\n<pre><code class=\"pgsql\">SELECT move(3,2);<\/code><\/pre>\n<p>\u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c\u0441\u044f \u043e\u0448\u0438\u0431\u043a\u043e\u0438\u0306, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0434\u0438\u0441\u043a 2 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u0435\u043d \u043d\u0430 \u0434\u0438\u0441\u043a 1 \u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e \u0434\u0438\u0430\u043c\u0435\u0442\u0440\u0430. <\/p>\n<h3>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u042d\u0442\u0443 \u0437\u0430\u0434\u0430\u0447\u0443 \u044f \u0434\u0430\u043b \u0438\u0437 \u0434\u0432\u0443\u0445 \u0441\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439. \u0412\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u0434\u043b\u044f \u0440\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u044f: \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0438\u0445 \u0437\u0430\u0434\u0430\u0447, \u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0438 \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e SQL-\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 (\u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e SQL, \u043d\u0438\u043a\u0430\u043a\u0438\u0435 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u043d\u0435 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b\u0438\u0441\u044c). \u0412\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u044f \u0441\u0447\u0438\u0442\u0430\u044e \u0442\u0435\u043c\u0443 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438 \u043a\u0440\u0430\u0439\u043d\u0435 \u0432\u0430\u0436\u043d\u043e\u0439, \u043d\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u043b\u043e\u0445\u043e \u043f\u043e\u043d\u0438\u043c\u0430\u0435\u043c\u043e\u0439. \u041c\u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044e \u0437\u0430\u0431\u044b\u0432\u0430\u044e\u0442.<\/p>\n<p>\u0421 \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0441\u0445\u0435\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u043e\u0447\u0442\u0438 \u043d\u0438 \u0443 \u043a\u043e\u0433\u043e \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043d\u0435 \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u043e: \u043d\u0443\u0436\u043d\u0430 \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0439, \u0441\u0442\u0440\u043e\u043a\u0430 \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441 \u043d\u043e\u043c\u0435\u0440\u043e\u043c \u0434\u0438\u0441\u043a\u0430 \u0438 \u043d\u043e\u043c\u0435\u0440\u043e\u043c \u0441\u0442\u0435\u0440\u0436\u043d\u044f \u043e\u0437\u043d\u0430\u0447\u0430\u0435\u0442, \u0447\u0442\u043e \u0434\u0430\u043d\u043d\u044b\u0439 \u0434\u0438\u0441\u043a \u043d\u0430\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043d\u0430 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u0442\u0435\u0440\u0436\u043d\u0435.<\/p>\n<p>\u041f\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044e \u0437\u0430\u0434\u0430\u0447\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0437\u0430\u0432\u0435\u0440\u0448\u0430\u0442\u044c\u0441\u044f \u043e\u0448\u0438\u0431\u043a\u043e\u0439 \u043f\u0440\u0438 \u043f\u043e\u043f\u044b\u0442\u043a\u0435 \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435. \u0412 SQL \u043d\u0435\u0442 \u0442\u0430\u043a\u043e\u0439 \u0448\u0442\u0443\u043a\u0438, \u043a\u0430\u043a <code>RAISE EXCEPTION<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u043f\u0440\u043e\u044f\u0432\u043b\u044f\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0435\u0442\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c. \u041a\u0442\u043e-\u0442\u043e \u0434\u0435\u043b\u0438\u043b \u043d\u0430 \u043d\u043e\u043b\u044c, \u043a\u0442\u043e-\u0442\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u043b \u0432 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u0442\u0440\u043e\u043a. \u0412\u0441\u0435 \u044d\u0442\u043e \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b\u043e\u0441\u044c (\u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0441\u043a\u0430\u0437\u0430\u043d\u043e, \u0447\u0442\u043e \u043e\u0448\u0438\u0431\u043a\u0430 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043b\u044e\u0431\u043e\u0439), \u0445\u043e\u0442\u044f \u043d\u0430 \u043c\u043e\u0439 \u0432\u043a\u0443\u0441 \u043b\u0443\u0447\u0448\u0435, \u0447\u0442\u043e\u0431\u044b \u043e\u0448\u0438\u0431\u043a\u0430 \u0432\u044b\u0437\u0432\u0430\u043b\u0430\u0441\u044c \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u0435\u043c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u0438. \u0418\u0441\u0445\u043e\u0434\u044f \u0438\u0437 \u044d\u0442\u043e\u0433\u043e \u0432 \u0441\u0432\u043e\u0435\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u044f \u0441\u043e\u0437\u0434\u0430\u043b \u0442\u0430\u043a\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443:<\/p>\n<pre><code class=\"pgsql\">CREATE TABLE hanoi(   disk integer,   rod integer NOT NULL CHECK (rod BETWEEN 1 AND 64),   chk boolean NOT NULL CHECK (chk) );<\/code><\/pre>\n<p>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0441\u0442\u043e\u043b\u0431\u0446\u0430 <code>disk<\/code> \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442, \u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0442\u0430\u0431\u043b\u0438\u0446\u0430 \u0438\u0437\u043d\u0430\u0447\u0430\u043b\u044c\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u0443\u0436\u043d\u044b\u043c\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438, \u0430 \u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u0431\u0443\u0434\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e \u043d\u043e\u043c\u0435\u0440 \u0441\u0442\u0435\u0440\u0436\u043d\u044f. \u0422\u0430\u043a\u0436\u0435 \u0437\u0434\u0435\u0441\u044c \u043d\u0435\u0442 \u043f\u0435\u0440\u0432\u0438\u0447\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430: \u0432 \u043c\u043e\u0435\u043c \u0440\u0435\u0448\u0435\u043d\u0438\u0438 \u044d\u0442\u043e \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u043e \u0431\u044b \u0433\u0430\u0440\u0430\u043d\u0442\u0438\u0439 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u043e\u0441\u0442\u0438, \u0437\u0430\u0442\u043e \u0441\u043e\u0437\u0434\u0430\u043b\u043e \u0431\u044b \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0439 \u0434\u043b\u044f \u0442\u0430\u043a\u043e\u0439 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438\u043d\u0434\u0435\u043a\u0441.<\/p>\n<p>\u0412 \u0441\u0442\u043e\u043b\u0431\u0435\u0446 <code>chk<\/code> \u044f \u0431\u0443\u0434\u0443 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c <code>false<\/code>, \u043a\u043e\u0433\u0434\u0430 \u043c\u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0431\u0440\u043e\u0441\u0438\u0442\u044c \u0438\u0441\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435.<\/p>\n<p>\u041a\u0442\u043e-\u0442\u043e \u043f\u043e\u0448\u0435\u043b \u0434\u0440\u0443\u0433\u0438\u043c \u043f\u0443\u0442\u0435\u043c: \u0441\u043e\u0437\u0434\u0430\u043b \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0441\u0442\u0435\u0440\u0436\u043d\u0435\u0439, \u0432 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0434\u0438\u0441\u043a\u043e\u0432:<\/p>\n<pre><code class=\"pgsql\">CREATE TABLE rods(   rod integer, -- PRIMARY KEY   disks integer[] );<\/code><\/pre>\n<p>\u041c\u043e\u0436\u043d\u043e \u0438 \u0442\u0430\u043a, \u043d\u043e \u043f\u0435\u0440\u0435\u043d\u043e\u0441 \u0434\u0438\u0441\u043a\u0430 \u0441\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f \u043d\u0430 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c \u0431\u0443\u0434\u0435\u0442 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 <code>UPDATE<\/code>, \u0430 \u044d\u0442\u043e \u043d\u0435 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438.<\/p>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>move<\/code>.<\/p>\n<p>\u041a\u0430\u043a \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u043d\u0430 \u0432\u0445\u043e\u0434 \u0435\u0439 \u043c\u043e\u0433\u0443\u0442 \u043f\u043e\u0434\u0430\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435: \u043d\u043e\u043c\u0435\u0440 \u043d\u0435\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f \u0438\u043b\u0438 \u0434\u0438\u0441\u043a\u0430 (\u0432\u043a\u043b\u044e\u0447\u0430\u044f <code>NULL<\/code>, \u043e \u0447\u0435\u043c \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0437\u0430\u0431\u044b\u043b\u0438). \u041a\u0440\u043e\u043c\u0435 \u0442\u043e\u0433\u043e, \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043d\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438:<\/p>\n<ul>\n<li>\n<p>\u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u0435 \u0434\u0438\u0441\u043a\u0430 \u0441\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f \u043d\u0430 \u0442\u043e\u0442 \u0436\u0435 \u0441\u0430\u043c\u044b\u0439 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c;<\/p>\n<\/li>\n<li>\n<p>\u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0432\u0437\u044f\u0442\u044c \u0434\u0438\u0441\u043a \u0441 \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f;<\/p>\n<\/li>\n<li>\n<p>\u043f\u0435\u0440\u0435\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u043d\u0438\u0435 \u0434\u0438\u0441\u043a\u0430 \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u0434\u0438\u0430\u043c\u0435\u0442\u0440\u0430 \u043d\u0430 \u0434\u0438\u0441\u043a \u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e \u0434\u0438\u0430\u043c\u0435\u0442\u0440\u0430.<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u043b\u043e\u0441\u044c \u0434\u0432\u0443\u043c\u044f \u0442\u0435\u0441\u0442\u0430\u043c\u0438. \u041f\u0440\u043e\u0441\u0442\u043e\u0439 \u00absmoke-\u0442\u0435\u0441\u0442\u00bb \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u043b \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u043d\u0435\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0439 \u0434\u0438\u0441\u043a\u043e\u0432, \u043a\u0430\u043a \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445, \u0442\u0430\u043a \u0438 \u043d\u0435\u0442. \u0412\u0442\u043e\u0440\u043e\u0439 \u0442\u0435\u0441\u0442 \u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043b \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u0443\u044e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438\u0437 50 \u0442\u044b\u0441\u044f\u0447 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 (\u043a\u0430\u043a \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u044b\u0445, \u0442\u0430\u043a \u0438 \u043d\u0435\u0442) \u0438 \u0441\u0432\u0435\u0440\u044f\u043b \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c, \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u043c \u043e\u0442 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u043d\u043e\u0439 \u00ab\u044d\u0442\u0430\u043b\u043e\u043d\u043d\u043e\u0439\u00bb \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 (\u044f \u043d\u0430\u043f\u0438\u0441\u0430\u043b \u0435\u0435 \u043d\u0430 PL\/pgSQL).<\/p>\n<p>\u041f\u0440\u043e\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u044d\u0442\u0438\u0445 \u0442\u0435\u0441\u0442\u043e\u0432 \u0434\u0430\u0432\u0430\u043b\u043e \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0443 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0431\u0430\u043b\u043b\u043e\u0432. \u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u043f\u043e\u0440\u0430 \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0441\u043f\u0440\u0430\u0432\u0438\u0442\u0441\u044f \u0441 \u044d\u0442\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439:<\/p>\n<pre><code class=\"pgsql\">CREATE FUNCTION move(rod_from integer, rod_to integer) RETURNS integer LANGUAGE sql AS $$   -- ...\u0442\u0443\u0442 \u043f\u043e\u043a\u0430 \u043a\u043e\u0435-\u0447\u0435\u0433\u043e \u043d\u0435 \u0445\u0432\u0430\u0442\u0430\u0435\u0442...   UPDATE hanoi h   SET rod = rod_to,       chk = disk &lt; coalesce(( -- \u043d\u0435\u043b\u044c\u0437\u044f \u043a\u043b\u0430\u0441\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0439 \u043d\u0430 \u043c\u0435\u043d\u044c\u0448\u0438\u0439 \u0438 \u0441\u0430\u043c \u043d\u0430 \u0441\u0435\u0431\u044f         SELECT min(disk)         FROM hanoi         WHERE rod = rod_to       ),65)       AND ( -- \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043d\u0435\u043f\u0443\u0441\u0442\u044b\u043c         SELECT min(disk)         FROM hanoi         WHERE rod = rod_from       ) IS NOT NULL   WHERE disk = coalesce((     SELECT min(disk) -- \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u0434\u0438\u0441\u043a     FROM hanoi     WHERE rod = rod_from   ),1) -- \u043d\u0430\u0434\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b update \u043c\u043e\u0433 \u0441\u043b\u043e\u043c\u0430\u0442\u044c\u0441\u044f \u043d\u0430 chk   RETURNING disk; $$;<\/code><\/pre>\n<p>\u0414\u0440\u0443\u0433\u0430\u044f \u043f\u043e\u043b\u043e\u0432\u0438\u043d\u0430 \u0431\u0430\u043b\u043b\u043e\u0432 \u043f\u0440\u0438\u0447\u0438\u0442\u0430\u043b\u0430\u0441\u044c \u0440\u0435\u0448\u0435\u043d\u0438\u044f\u043c, \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u043c \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f.<\/p>\n<p>\u0412 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u043d\u0430\u043c \u043d\u0435 \u0441\u043a\u0430\u0437\u0430\u043b\u0438, \u043a\u0430\u043a\u043e\u0439 \u0443\u0440\u043e\u0432\u0435\u043d\u044c \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u043c\u043e\u043d\u0430\u0445\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0440\u0430\u0441\u0441\u0447\u0438\u0442\u044b\u0432\u0430\u0442\u044c \u043d\u0430 \u0445\u0443\u0434\u0448\u0435\u0435 (\u0438, \u0432 \u0442\u043e \u0436\u0435 \u0432\u0440\u0435\u043c\u044f, \u0441\u0430\u043c\u043e\u0435 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u043d\u043e\u0435) \u2014 Read Committed. \u041d\u0430 \u044d\u0442\u043e\u043c \u0443\u0440\u043e\u0432\u043d\u0435 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u0438 \u0443 \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u2014 \u0441\u0432\u043e\u0439 \u0441\u043d\u0438\u043c\u043e\u043a \u0434\u0430\u043d\u043d\u044b\u0445. \u0427\u0435\u043c \u043d\u0430\u043c \u044d\u0442\u043e \u0433\u0440\u043e\u0437\u0438\u0442?<\/p>\n<p>\u0412 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0435 \u0441 \u043c\u0430\u0441\u0441\u0438\u0432\u0430\u043c\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"pgsql\">... ... \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0441\u0442\u0438 ... UPDATE rods SET disks = ... WHERE red = rod_from; UPDATE rods SET disks = ... WHERE red = rod_to; ...<\/code><\/pre>\n<p>\u041c\u0435\u0436\u0434\u0443 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u043e\u0439, \u043f\u0435\u0440\u0432\u044b\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0438 \u0432\u0442\u043e\u0440\u044b\u043c \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0442\u0438 \u0432\u0441\u0435 \u0447\u0442\u043e \u0443\u0433\u043e\u0434\u043d\u043e. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043a\u0442\u043e-\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0443\u0431\u0440\u0430\u0442\u044c \u0434\u0438\u0441\u043a \u0441\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f <code>rod_from<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u044b \u0441\u043e\u0431\u0440\u0430\u043b\u0438\u0441\u044c \u043f\u0435\u0440\u0435\u0441\u0442\u0430\u0432\u0438\u0442\u044c. \u0418\u043b\u0438 \u0443\u0441\u043f\u0435\u0442\u044c \u043f\u043e\u043b\u043e\u0436\u0438\u0442\u044c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u0434\u0438\u0441\u043a \u043d\u0430 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c <code>rod_to<\/code>, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0447\u0435\u0433\u043e \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0441\u0442\u0430\u043d\u0435\u0442 \u043d\u0435\u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u043c. \u0412\u0441\u0435 \u044d\u0442\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u0442 \u043a \u043d\u0430\u0440\u0443\u0448\u0435\u043d\u0438\u044e \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u043e\u0441\u0442\u0438, \u0445\u043e\u0442\u044f, \u043f\u043e\u043a\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u043b\u0430\u0441\u044c \u0432 \u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u043c \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0435, \u043e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u0442\u0430\u043a\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u043b\u0430 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u0438, \u043d\u0430\u0434\u043e \u043f\u0435\u0440\u0435\u0434 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0432\u0435\u0440\u043e\u043a \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c <em>\u043e\u0431\u0430<\/em> \u0441\u0442\u0435\u0440\u0436\u043d\u044f <code>rod_from<\/code> \u0438 <code>rod_to<\/code>. \u0412 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u043c \u0443\u0436\u0435 \u043d\u0438\u043a\u0442\u043e \u043d\u0435 \u0441\u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u043c\u0435\u0448\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u0434\u0438\u0441\u043a \u0441 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u0442\u0435\u0440\u0436\u043d\u044f \u043d\u0430 \u0434\u0440\u0443\u0433\u043e\u0439.<\/p>\n<p>\u041d\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u043e \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u043e\u0432, \u0434\u043e\u0431\u0440\u0430\u0432\u0448\u0438\u0445\u0441\u044f \u0434\u043e \u043c\u044b\u0441\u043b\u0438 \u043e \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u0438, \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043b\u0438 \u0432\u0441\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443, \u043e\u0431\u044b\u0447\u043d\u043e \u0432 \u0438\u0441\u043a\u043b\u044e\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435 (<code>LOCK TABLE<\/code>). \u0411\u0435\u0437\u0443\u0441\u043b\u043e\u0432\u043d\u043e, \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442, \u043d\u043e \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u0442\u044c \u0434\u0438\u0441\u043a\u0438 \u0438 \u043c\u0435\u0436\u0434\u0443 \u0434\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u0442\u0435\u0440\u0436\u043d\u044f\u043c\u0438, \u0447\u0442\u043e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u043e\u0441\u0430\u0436\u0438\u0432\u0430\u0435\u0442 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u042f\u043d \u0421\u0435\u043d\u0438\u043d \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0441\u044f \u0434\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0434\u0432\u0430 \u0441\u0442\u0435\u0440\u0436\u043d\u044f, \u043d\u043e \u043f\u043e\u043f\u0430\u043b\u0441\u044f \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u043b\u043e\u0432\u0443\u0448\u043a\u0443: \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 \u0441\u0442\u0440\u043e\u043a (<code>SELECT ... FOR UPDATE<\/code>) \u2014 \u0437\u0430\u0442\u0440\u0430\u0442\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0435 \u0441 \u0437\u0430\u043f\u0438\u0441\u044c\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438 \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0443 \u0434\u0430\u043d\u043d\u044b\u0445. \u041d\u0430 \u043c\u043e\u0435\u0439 \u0442\u0435\u0441\u0442\u043e\u0432\u043e\u0439 \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0435 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 <code>LOCK TABLE<\/code> \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u043e\u0449\u0443\u0442\u0438\u043c\u043e, \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 20, \u0431\u044b\u0441\u0442\u0440\u0435\u0435.<\/p>\n<p>\u0415\u0449\u0435 \u043e\u0434\u043d\u0430 \u043b\u043e\u0432\u0443\u0448\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u043f\u043e\u0434\u0441\u0442\u0435\u0440\u0435\u0433\u0430\u0435\u0442 \u043f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u043c\u0438 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438 \u2014 \u044d\u0442\u043e \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u0421\u0442\u0435\u0440\u0436\u043d\u0438 \u043d\u0430\u0434\u043e \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u043e\u0434\u043d\u043e\u043c \u0438 \u0442\u043e\u043c \u0436\u0435 \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043e\u0442 \u043c\u0435\u043d\u044c\u0448\u0435\u0433\u043e \u043a \u0431\u043e\u043b\u044c\u0448\u0435\u043c\u0443, \u0438\u043d\u0430\u0447\u0435 \u0431\u0443\u0434\u0443\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0433\u0443\u0431\u044f\u0442 \u0432\u0441\u044e \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c.<\/p>\n<p>\u0425\u043e\u0440\u043e\u0448\u043e, \u0430 \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a \u0441 \u043c\u043e\u0438\u043c \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u043c, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438, \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 <em>\u043e\u0434\u043d\u043e\u043c<\/em> \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0435, \u0438\u0437\u043c\u0435\u043d\u044f\u044e\u0449\u0435\u043c <em>\u043e\u0434\u043d\u0443<\/em> \u0441\u0442\u0440\u043e\u043a\u0443?  \u0420\u043e\u0432\u043d\u043e \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435: \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0430 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438 (\u0442\u043e \u0435\u0441\u0442\u044c \u043f\u0430\u0440\u044b \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c\u2014\u0434\u0438\u0441\u043a) \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442 \u043e\u0431\u0430 \u0441\u0442\u0435\u0440\u0436\u043d\u044f. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u0432\u0430 \u0442\u0430\u043a\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043c\u043e\u0433\u0443\u0442 \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u043f\u0435\u0440\u0435\u043d\u0435\u0441\u0442\u0438 \u043d\u0430 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c \u0434\u0438\u0441\u043a\u0438 \u0440\u0430\u0437\u043d\u044b\u0445 \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u0432, \u0430 \u0437\u0430\u0442\u0435\u043c \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c\u0441\u044f \u0432 \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e\u043c \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435 \u0447\u0435\u0433\u043e \u043e\u043a\u0430\u0436\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0431\u043e\u043b\u044c\u0448\u0438\u0439 \u0434\u0438\u0441\u043a \u043f\u043e\u043b\u043e\u0436\u0438\u043b\u0438 \u043d\u0430 \u043c\u0435\u043d\u044c\u0448\u0438\u0439.<\/p>\n<p>\u041f\u043e\u043d\u044f\u0442\u043d\u043e, \u0447\u0442\u043e <code>LOCK TABLE<\/code> \u0441\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043d\u043e \u043a\u0430\u043a \u0437\u0430\u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0435\u0440\u0436\u043d\u0438? \u0410 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0432 PostgreSQL \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c <a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/16\/explicit-locking#ADVISORY-LOCKS\">\u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043a \u0442\u043e\u043c\u0443 \u0436\u0435 \u0438 \u0431\u044b\u0441\u0442\u0440\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442. \u0422\u0430\u043a\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0432 \u043c\u043e\u0438\u0445 \u0442\u0435\u0441\u0442\u0430\u0445 \u043e\u043a\u0430\u0437\u0430\u043b\u0441\u044f \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u043d\u0442\u043e\u0432 \u043d\u0430 15. \u0414\u043e \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043e\u043a \u0434\u043e\u0433\u0430\u0434\u0430\u043b\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0410\u043d\u0434\u0440\u0435\u0439 \u041a\u0443\u0434\u0438\u043d\u043e\u0432; \u043a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0434\u043e\u0441\u0430\u0434\u043d\u0430\u044f \u043e\u0448\u0438\u0431\u043a\u0430 \u043f\u043e\u043c\u0435\u0448\u0430\u043b\u0430 \u0435\u043c\u0443 \u0432\u044b\u0440\u0432\u0430\u0442\u044c\u0441\u044f \u0432\u043f\u0435\u0440\u0435\u0434.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"pgsql\">CREATE TABLE hanoi(   disk integer,   rod integer NOT NULL CHECK (rod BETWEEN 1 AND 64),   chk boolean NOT NULL CHECK (chk) ); INSERT INTO hanoi   SELECT disk, 1, true FROM generate_series(1,64) disk;  CREATE FUNCTION move(rod_from integer, rod_to integer) RETURNS integer LANGUAGE sql AS $$   SELECT pg_advisory_xact_lock(least(rod_from,rod_to));   SELECT pg_advisory_xact_lock(greatest(rod_from,rod_to));   UPDATE hanoi h   SET rod = rod_to,       chk = disk &lt; coalesce(( -- \u043d\u0435\u043b\u044c\u0437\u044f \u043a\u043b\u0430\u0441\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u0439 \u043d\u0430 \u043c\u0435\u043d\u044c\u0448\u0438\u0439 \u0438 \u0441\u0430\u043c \u043d\u0430 \u0441\u0435\u0431\u044f         SELECT min(disk)         FROM hanoi         WHERE rod = rod_to       ),65)       AND ( -- \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0441\u0442\u0435\u0440\u0436\u0435\u043d\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0431\u044b\u0442\u044c \u043d\u0435\u043f\u0443\u0441\u0442\u044b\u043c         SELECT min(disk)         FROM hanoi         WHERE rod = rod_from       ) IS NOT NULL   WHERE disk = coalesce((     SELECT min(disk) -- \u0432\u0435\u0440\u0445\u043d\u0438\u0439 \u0434\u0438\u0441\u043a     FROM hanoi     WHERE rod = rod_from   ),1) -- \u043d\u0430\u0434\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0432\u044b\u0431\u0440\u0430\u0442\u044c, \u0447\u0442\u043e\u0431\u044b update \u043c\u043e\u0433 \u0441\u043b\u043e\u043c\u0430\u0442\u044c\u0441\u044f \u043d\u0430 chk   RETURNING disk; $$;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0414\u043b\u044f \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u044f\u0445 \u043a\u043e\u043d\u043a\u0443\u0440\u0435\u043d\u0442\u043d\u043e\u0441\u0442\u0438 \u044f \u043f\u043e\u0441\u0442\u0443\u043f\u0438\u043b \u0442\u0430\u043a:<\/p>\n<ol>\n<li>\n<p>\u041f\u043e\u0434\u0430\u0432\u0430\u043b \u0442\u0435\u0441\u0442\u043e\u0432\u0443\u044e \u043d\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u0432 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0432. \u041f\u043e\u0441\u043b\u0435 \u0432\u044b\u0437\u043e\u0432\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u043b \u043d\u043e\u043c\u0435\u0440 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0438 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0436\u0443\u0440\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443.<\/p>\n<\/li>\n<li>\n<p>\u0412 \u043a\u043e\u043d\u0446\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u043b \u0436\u0443\u0440\u043d\u0430\u043b\u044c\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0432\u0440\u0435\u043c\u0435\u043d\u0435\u043c \u0444\u0438\u043a\u0441\u0430\u0446\u0438\u0438 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0439 (\u0441\u043c. \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 <a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/16\/runtime-config-replication#GUC-TRACK-COMMIT-TIMESTAMP\"><em>track_commit_timestamp<\/em><\/a> \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044e <a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/16\/functions-info#FUNCTIONS-INFO-COMMIT-TIMESTAMP\">pg_xact_commit_timestamp<\/a>), \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u044f \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0421\u0432\u0435\u0440\u044f\u043b \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432 \u0441 \u044d\u0442\u0430\u043b\u043e\u043d\u043d\u043e\u0439 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0435\u0439.<\/p>\n<\/li>\n<\/ol>\n<p>\u0412 \u0437\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435 \u043d\u0435 \u043c\u043e\u0433\u0443 \u043d\u0435 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c\u0441\u044f \u0440\u0430\u0434\u043e\u0441\u0442\u044c\u044e \u043e\u0442 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f \u0418\u043b\u044c\u0438 \u0414\u0435\u0440\u043a\u0441\u0435\u043d\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u043d \u043f\u0440\u043e\u0446\u0438\u0442\u0438\u0440\u043e\u0432\u0430\u043b <a href=\"https:\/\/users.ece.utexas.edu\/~adnan\/pike.html\">\u043f\u044f\u0442\u044c \u043f\u0440\u0430\u0432\u0438\u043b \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0420\u043e\u0431\u0430 \u041f\u0430\u0439\u043a\u0430<\/a>, \u0438 \u0437\u0430\u0442\u0435\u043c \u0447\u0435\u0441\u0442\u043d\u043e \u043f\u044b\u0442\u0430\u043b\u0441\u044f \u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u044c \u0438\u043c (\u044f, \u043f\u0440\u0430\u0432\u0434\u0430, \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u0447\u0438\u0442\u0430\u043b, \u0447\u0442\u043e \u043f\u0440\u043e \u043f\u0440\u0435\u0436\u0434\u0435\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0446\u0438\u044e \u0441\u043a\u0430\u0437\u0430\u043b \u041a\u043d\u0443\u0442).<\/p>\n<p>\u041d\u0443 \u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0447\u0435\u0440\u0435\u0437 \u043c\u0435\u0441\u044f\u0446 \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043e \u0442\u043e\u043c, \u043a\u0430\u043a \u043f\u0440\u043e\u0448\u0435\u043b \u0444\u0438\u043d\u0430\u043b \u043e\u043b\u0438\u043c\u043f\u0438\u0430\u0434\u044b. Stay tuned!<\/p>\n<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/808211\/\"> https:\/\/habr.com\/ru\/articles\/808211\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u0412\u0434\u043e\u0445\u043d\u043e\u0432\u0438\u0432\u0448\u0438\u0441\u044c \u043f\u0440\u043e\u0448\u043b\u043e\u0433\u043e\u0434\u043d\u0438\u043c \u043e\u043f\u044b\u0442\u043e\u043c, \u043c\u044b <a href=\"https:\/\/habr.com\/ru\/companies\/postgrespro\/articles\/742684\/\">\u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u043b\u0438 \u043d\u0430\u0447\u0438\u043d\u0430\u043d\u0438\u0435<\/a> \u0438 \u0441\u043d\u043e\u0432\u0430 \u043f\u0440\u043e\u0432\u043e\u0434\u0438\u043c \u043a\u043e\u043d\u043a\u0443\u0440\u0441 \u043f\u043e SQL \u043d\u0430 \u043c\u0435\u0436\u0434\u0443\u043d\u0430\u0440\u043e\u0434\u043d\u043e\u0439 \u043e\u043b\u0438\u043c\u043f\u0438\u0430\u0434\u0435 \u00ab<a href=\"https:\/\/world-it-planet.org\/\">IT-\u041f\u043b\u0430\u043d\u0435\u0442\u0430<\/a>\u00bb.<\/p>\n<p>\u041a\u043e\u043d\u043a\u0443\u0440\u0441 \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0442\u0440\u0435\u0445 \u044d\u0442\u0430\u043f\u043e\u0432. \u0417\u0430\u043e\u0447\u043d\u044b\u0439 \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0435\u0441\u0442 \u0441\u043e\u0431\u0440\u0430\u043b \u043f\u043e\u0447\u0442\u0438 3000 \u0447\u0435\u043b\u043e\u0432\u0435\u043a, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u044d\u0442\u0430\u043f \u043c\u044b \u043e\u0442\u043e\u0431\u0440\u0430\u043b\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e 200. \u0412\u043e\u043f\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u044d\u0442\u0430\u043f\u0430 \u0431\u044b\u043b\u0438 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d\u044b \u043c\u043e\u0438\u043c \u043a\u043e\u043b\u043b\u0435\u0433\u043e\u0439, \u0415\u0432\u0433\u0435\u043d\u0438\u0435\u043c \u0414\u0430\u0432\u044b\u0434\u043e\u0432\u044b\u043c.<\/p>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u044d\u0442\u0430\u043f \u2014 \u0442\u0430\u043a\u0436\u0435 \u0437\u0430\u043e\u0447\u043d\u044b\u0439. \u0417\u0434\u0435\u0441\u044c \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a\u0430\u043c \u0431\u044b\u043b\u043e \u043f\u0440\u0435\u0434\u043b\u043e\u0436\u0435\u043d\u043e \u043f\u043e\u0434\u0443\u043c\u0430\u0442\u044c \u043d\u0430\u0434 \u043f\u044f\u0442\u044c\u044e \u0437\u0430\u0434\u0430\u0447\u0430\u043c\u0438 \u043c\u043e\u0435\u0433\u043e \u0430\u0432\u0442\u043e\u0440\u0441\u0442\u0432\u0430, \u043e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044f \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u0438 \u0445\u043e\u0447\u0443 \u0440\u0430\u0441\u0441\u043a\u0430\u0437\u0430\u0442\u044c.<\/p>\n<p>\u0422\u0440\u0435\u0442\u0438\u0439 \u2014 \u043e\u0447\u043d\u044b\u0439 \u2014 \u044d\u0442\u0430\u043f \u043f\u0440\u043e\u0439\u0434\u0435\u0442 \u0432 \u043a\u043e\u043d\u0446\u0435 \u043c\u0430\u044f; \u043f\u043e\u0441\u0442\u0430\u0440\u0430\u044e\u0441\u044c \u043d\u0435 \u0437\u0430\u0442\u044f\u0433\u0438\u0432\u0430\u0442\u044c \u0441 \u043e\u0442\u0447\u0435\u0442\u043e\u043c, \u043d\u043e \u043f\u043e\u043a\u0430 \u0445\u0440\u0430\u043d\u044e \u0438\u043d\u0442\u0440\u0438\u0433\u0443\u044e\u0449\u0435\u0435 \u043c\u043e\u043b\u0447\u0430\u043d\u0438\u0435.<\/p>\n<p>\u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0432\u0441\u0435 \u0432\u0432\u043e\u0434\u043d\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u043f\u0440\u043e \u043c\u043e\u0442\u0438\u0432\u0430\u0446\u0438\u044e \u044f \u0443\u0436\u0435 \u0441\u043a\u0430\u0437\u0430\u043b \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0439 \u0440\u0430\u0437, \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0438\u0441\u0442\u0443\u043f\u0438\u043c \u043a \u0434\u0435\u043b\u0443.<\/p>\n<h2>\u0417\u0430\u0434\u0430\u0447\u0430 1. \u041c\u043d\u043e\u0433\u043e\u0433\u043e\u043b\u043e\u0432\u044b\u0439 \u0426\u0435\u0440\u0431\u0435\u0440<\/h2>\n<h3>\u0423\u0441\u043b\u043e\u0432\u0438\u0435<\/h3>\n<p>\u0412\u0445\u043e\u0434 \u0432 \u043f\u043e\u0434\u0437\u0435\u043c\u0435\u043b\u044c\u0435 \u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043c\u043d\u043e\u0433\u043e\u0433\u043e\u043b\u043e\u0432\u044b\u0438\u0306 \u043f\u0435\u0441. \u041c\u0443\u0437\u044b\u043a\u0430 \u043d\u0430 \u043d\u0435\u0433\u043e \u043d\u0435 \u0434\u0435\u0438\u0306\u0441\u0442\u0432\u0443\u0435\u0442, \u043d\u043e \u0432\u0440\u0435\u043c\u044f \u043e\u0442 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0438\u0437 \u0433\u043e\u043b\u043e\u0432 \u043e\u0442\u0434\u044b\u0445\u0430\u044e\u0442. \u0413\u0430\u0440\u0440\u0438 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b \u043d\u0430 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u043c \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u0432\u0438\u0434\u0435\u043e\u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0433\u043e\u043b\u043e\u0432. \u0421\u0438\u0441\u0442\u0435\u043c\u0430 \u043d\u0430\u0434\u0435\u0436\u043d\u043e \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u0435\u0442 \u0437\u0430\u0441\u044b\u043f\u0430\u043d\u0438\u044f \u0438 \u043f\u0440\u043e\u0441\u044b\u043f\u0430\u043d\u0438\u044f \u0433\u043e\u043b\u043e\u0432, \u043d\u043e \u043c\u043e\u0436\u0435\u0442 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0438 \u0432 \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u043b\u044c\u043d\u044b\u0435 \u043f\u0440\u043e\u043c\u0435\u0436\u0443\u0442\u043e\u0447\u043d\u044b\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b. <\/p>\n<p>\u0418\u0437\u0432\u0435\u0441\u0442\u043d\u043e, \u0447\u0442\u043e \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0432\u0441\u0435 \u0433\u043e\u043b\u043e\u0432\u044b \u0431\u043e\u0434\u0440\u0441\u0442\u0432\u043e\u0432\u0430\u043b\u0438, \u0430 \u0437\u0430 \u043f\u0435\u0440\u0438\u043e\u0434 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u0430\u044f \u0438\u0437 \u0433\u043e\u043b\u043e\u0432 \u0437\u0430\u0441\u044b\u043f\u0430\u043b\u0430 \u0445\u043e\u0442\u044f \u0431\u044b \u0440\u0430\u0437. <\/p>\n<p>\u0412\u044b\u0432\u0435\u0434\u0438\u0442\u0435 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b \u0432\u0440\u0435\u043c\u0435\u043d\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0413\u0430\u0440\u0440\u0438 \u0438 \u0435\u0433\u043e \u0434\u0440\u0443\u0437\u044c\u044f \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043f\u0440\u043e\u0431\u0440\u0430\u0442\u044c\u0441\u044f \u043c\u0438\u043c\u043e \u043f\u0441\u0430. <\/p>\n<p>\u0421\u043e\u0431\u044b\u0442\u0438\u044f \u0444\u0438\u043a\u0441\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0435 cerberus: <\/p>\n<pre><code class=\"pgsql\">CREATE TABLE cerberus(   head_id integer NOT NULL,      -- \u043d\u043e\u043c\u0435\u0440 \u0433\u043e\u043b\u043e\u0432\u044b   event_time timestamp NOT NULL, -- \u0432\u0440\u0435\u043c\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f   head_state boolean NOT NULL,   -- true - \u0431\u043e\u0434\u0440\u0441\u0442\u0432\u0443\u0435\u0442, false - \u0441\u043f\u0438\u0442   UNIQUE (head_id, event_time) );<\/code><\/pre>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u044b (\u0432 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f), \u0432 \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0441\u0435 \u0433\u043e\u043b\u043e\u0432\u044b \u0441\u043f\u0430\u043b\u0438. <\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0440 <\/h4>\n<p>\u0414\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 <\/p>\n<pre><code class=\"pgsql\">INSERT INTO cerberus VALUES   (1, '2024-04-01 01:00:00'::timestamp, false), -- 1-\u044f \u0443\u0441\u043d\u0443\u043b\u0430   (3, '2024-04-01 02:00:00'::timestamp, false), -- 3-\u044f \u0443\u0441\u043d\u0443\u043b\u0430   (2, '2024-04-01 03:00:00'::timestamp, false), -- 2-\u044f \u0443\u0441\u043d\u0443\u043b\u0430   (2, '2024-04-01 04:00:00'::timestamp, true),  -- 2-\u044f \u043f\u0440\u043e\u0441\u043d\u0443\u043b\u0430\u0441\u044c   (1, '2024-04-01 04:30:00'::timestamp, false), -- 1-\u044f \u0441\u043f\u0438\u0442   (1, '2024-04-01 05:00:00'::timestamp, true),  -- 1-\u044f \u043f\u0440\u043e\u0441\u043d\u0443\u043b\u0430\u0441\u044c   (3, '2024-04-01 06:00:00'::timestamp, true);  -- 3-\u044f \u043f\u0440\u043e\u0441\u043d\u0443\u043b\u0430\u0441\u044c <\/code><\/pre>\n<p>\u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438: <\/p>\n<pre><code>      time_from      |       time_to ---------------------+---------------------  2024-04-01 03:00:00 | 2024-04-01 04:00:00 (1 rows) <\/code><\/pre>\n<p>(\u0412 \u0443\u0441\u043b\u043e\u0432\u0438\u0438 \u0437\u0430\u0434\u0430\u0447\u0438 \u044f \u043d\u0435 \u0432\u043f\u043e\u043b\u043d\u0435 \u0447\u0435\u0442\u043a\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u043b, \u0447\u0442\u043e \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438 \u0437\u0430\u043f\u0440\u043e\u0441, \u0435\u0441\u043b\u0438 \u0432 \u043a\u043e\u043d\u0446\u0435 \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u044f \u0432\u0441\u0435 \u0433\u043e\u043b\u043e\u0432\u044b \u0441\u043f\u044f\u0442. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u043b \u043b\u044e\u0431\u043e\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442.)<\/p>\n<h3>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0417\u0430\u0434\u0430\u0447\u0430 \u0432\u0438\u0434\u0435\u043b\u0430\u0441\u044c \u043c\u043d\u0435 \u043a\u0430\u043a \u0430\u043f\u0435\u0440\u0438\u0442\u0438\u0432 \u0434\u043b\u044f \u0440\u0430\u0437\u043c\u0438\u043d\u043a\u0438 \u043f\u0435\u0440\u0435\u0434 \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u043c \u0431\u043b\u044e\u0434\u043e\u043c, \u043d\u043e \u0441\u043e \u0441\u0432\u043e\u0435\u0439 \u0438\u0437\u044e\u043c\u0438\u043d\u043a\u043e\u0439. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u0435\u0448\u0430\u0442\u044c \u0435\u0435 \u043c\u043e\u0436\u043d\u043e \u0438 \u0442\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u044b\u043c\u0438 \u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0430\u043c\u0438, \u043d\u043e \u0435\u0441\u043b\u0438 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u0442\u044c, \u0447\u0442\u043e PostgreSQL \u0443\u043c\u0435\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0441 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430\u043c\u0438, \u0430 \u043d\u0430\u0447\u0438\u043d\u0430\u044f \u0441 14-\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u2014 \u0438 \u0441 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430\u043c\u0438, \u0436\u0438\u0442\u044c \u0441\u0440\u0430\u0437\u0443 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0432\u0435\u0441\u0435\u043b\u0435\u0435 \u0438 \u043f\u0440\u043e\u0449\u0435.<\/p>\n<p>\u0412\u0441\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u0441\u0432\u043e\u0434\u0438\u0442\u0441\u044f \u043a \u0442\u043e\u043c\u0443, \u0447\u0442\u043e\u0431\u044b \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u043e\u043b\u043e\u0432\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b \u0441\u043d\u0430 \u0438 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u0438\u0445 \u0432 \u043e\u0434\u0438\u043d \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d, \u0430 \u0437\u0430\u0442\u0435\u043c \u043d\u0430\u0439\u0442\u0438 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432 \u0432\u0441\u0435\u0445 \u0433\u043e\u043b\u043e\u0432.<\/p>\n<p>\u0414\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b \u0441\u043d\u0430 \u043b\u0435\u0433\u043a\u043e \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u044e\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043e\u043a\u043e\u043d\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>lead<\/code>: \u0431\u0435\u0440\u0435\u043c \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b \u043e\u0442 \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u0437\u0430\u0441\u044b\u043f\u0430\u043d\u0438\u044f \u0434\u043e \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e \u0437\u0430 \u043d\u0438\u043c \u0441\u043e\u0431\u044b\u0442\u0438\u044f. \u0427\u0442\u043e \u043f\u0440\u0438\u044f\u0442\u043d\u043e, \u043d\u0430\u043c \u043d\u0435 \u0432\u0430\u0436\u043d\u043e, \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043b\u0438 \u0437\u0430 \u0437\u0430\u0441\u044b\u043f\u0430\u043d\u0438\u0435\u043c \u043f\u0440\u043e\u0431\u0443\u0436\u0434\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u0430 \u043f\u043e\u0432\u0442\u043e\u0440\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u043b\u0430 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u0441\u043d\u0430: \u0432 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u0440\u0438\u043c\u044b\u043a\u0430\u044e\u0449\u0438\u0445 \u0434\u0440\u0443\u0433 \u043a \u0434\u0440\u0443\u0433\u0443 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432, \u044d\u0442\u043e \u043d\u0438 \u043d\u0430 \u0447\u0442\u043e \u043d\u0435 \u0432\u043b\u0438\u044f\u0435\u0442.<\/p>\n<p>\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432 \u0432 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u0438 \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u043c\u0443\u043b\u044c\u0442\u0438\u0437\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 <code>range_agg<\/code> \u0438 <code>range_intersect_agg<\/code>, \u0430 \u0440\u0430\u0437\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u043d\u044b\u0439 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d \u043f\u043e\u043b\u043d\u043e\u0433\u043e \u0441\u043d\u0430 \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b \u043c\u043e\u0436\u043d\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439 <code>unnest<\/code>. \u0412\u0441\u044e \u0441\u043b\u043e\u0436\u043d\u0443\u044e \u0438 \u0441\u043a\u0443\u0447\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 PostgreSQL \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0437\u0430 \u043d\u0430\u0441.<\/p>\n<details class=\"spoiler\">\n<summary>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"pgsql\">WITH ranges AS (   -- \u041e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u043c \u043f\u043e\u0434\u0440\u044f\u0434 \u0438\u0434\u0443\u0449\u0438\u0435 \u0441\u0442\u0440\u043e\u043a\u0438 (\u043d\u0430\u0447\u0438\u043d\u0430\u044f \u043e\u0442 \u0437\u0430\u0441\u044b\u043f\u0430\u043d\u0438\u044f) \u0432 \u043e\u0434\u0438\u043d \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d.   -- \u041f\u043e\u0432\u0442\u043e\u0440\u044f\u044e\u0449\u0438\u0435\u0441\u044f \u0441\u043e\u0431\u044b\u0442\u0438\u044f \u043d\u0430\u043c \u043d\u0435 \u043c\u0435\u0448\u0430\u044e\u0442: \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0438\u043d\u0442\u0435\u0440\u0432\u0430\u043b\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0434\u0430\u043b\u044c\u0448\u0435   -- \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u0441\u043e\u043b\u044c\u044e\u0442\u0441\u044f \u0432 \u043e\u0434\u0438\u043d \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d.   SELECT head_id, tsrange(event_time, next_time) off_range   FROM (     SELECT head_id, event_time, head_state,       lead(event_time) OVER (PARTITION BY head_id ORDER BY event_time) next_time     FROM cerberus   ) t      WHERE NOT head_state ), multiranges AS (   -- \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u043c \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u043e\u043b\u043e\u0432\u044b \u0432 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d   SELECT range_agg(off_range) off_multirange   FROM ranges   GROUP BY head_id ), intersections AS (   -- \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u0441\u0435\u0447\u0435\u043d\u0438\u0435 \u0432\u0441\u0435\u0445 \u043c\u0443\u043b\u044c\u0442\u0438\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432   SELECT unnest(range_intersect_agg(off_multirange)) off_range   FROM multiranges ) -- \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u0435\u043c \u0432 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0439 \u043f\u043e \u0443\u0441\u043b\u043e\u0432\u0438\u044e \u0432\u0438\u0434 SELECT lower(off_range), upper(off_range) FROM intersections;<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435 \u043d\u0430\u0448\u0435\u043b \u0442\u043e\u043b\u044c\u043a\u043e \u043e\u0434\u0438\u043d \u0443\u0447\u0430\u0441\u0442\u043d\u0438\u043a, \u041b\u0435\u043e\u043d\u0438\u0434 \u0410\u043b\u0435\u043a\u0441\u0435\u0435\u0432. \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u043c \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0440\u0430\u0441\u0447\u0435\u0445\u043b\u044f\u0442\u044c \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b, \u043c\u0430\u0441\u0441\u0438\u0432\u044b \u0438 \u0434\u0430\u0436\u0435 json-\u044b.<\/p>\n<h4>\u0420\u0443\u0431\u0440\u0438\u043a\u0430 \u00ab\u041d\u0435 \u0434\u0435\u043b\u0430\u0439\u0442\u0435 \u0442\u0430\u043a\u00bb<\/h4>\n<ul>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0435\u0441\u0442\u044c \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u044c, \u0447\u0442\u043e \u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u043e\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043d\u0435 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 <code>NULL<\/code>, \u043d\u0435 \u043d\u0430\u0434\u043e \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u0438\u0442\u044c \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 \u0442\u0438\u043f\u0430 <code>case when cnt.sleepHeadCnt = cnt.totalHeads then true else false end<\/code>. \u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c <code>cnt.sleepHeadCnt = cnt.totalHeads<\/code>. (\u0410 \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0439 \u0443\u0432\u0435\u0440\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u043d\u0435\u0442, \u043b\u0443\u0447\u0448\u0435 \u0443\u0436 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e\u0442 \u0444\u0430\u043a\u0442 \u0431\u043e\u043b\u0435\u0435 \u044f\u0432\u043d\u044b\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <code>coalesce<\/code>.)<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0431\u043e\u043b\u044c\u0448\u0438\u043d\u0441\u0442\u0432\u0435 \u0441\u043b\u0443\u0447\u0430\u0435\u0432 \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u0432\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u0442\u044c \u0434\u0440\u0443\u0433 \u0432 \u0434\u0440\u0443\u0433\u0430 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 <code>WITH<\/code>. \u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u043e\u0431\u0449\u0438\u0445 \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u043d\u0430\u0434 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u043a\u0430\u043a \u0440\u0430\u0437 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0438\u0445 \u043c\u043e\u0436\u043d\u043e \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0443\u043c\u0435\u043d\u044c\u0448\u0430\u044f \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u0438 \u0443\u043f\u0440\u043e\u0449\u0430\u044f \u0447\u0442\u0435\u043d\u0438\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430.<\/p>\n<\/li>\n<li>\n<p>\u0412\u044b\u0434\u0435\u043b\u044f\u0442\u044c \u043b\u0438 \u0437\u0430\u0433\u043b\u0430\u0432\u043d\u044b\u043c\u0438 \u043a\u043b\u044e\u0447\u0435\u0432\u044b\u0435 \u0441\u043b\u043e\u0432\u0430 \u2014 \u0434\u0435\u043b\u043e \u0432\u043a\u0443\u0441\u0430, \u043d\u043e \u043d\u0435 \u0441\u0442\u043e\u0438\u0442 \u043d\u0430\u0431\u0438\u0440\u0430\u0442\u044c \u0431\u043e\u043b\u044c\u0448\u0438\u043c\u0438 \u0431\u0443\u043a\u0432\u0430\u043c\u0438 \u0432\u0435\u0441\u044c \u0437\u0430\u043f\u0440\u043e\u0441. \u0412\u0441\u0435-\u0442\u0430\u043a\u0438 \u0434\u0432\u0430\u0434\u0446\u0430\u0442\u044c \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0435\u043a \u043d\u0430 \u0434\u0432\u043e\u0440\u0435, \u0432\u043e\u0441\u044c\u043c\u0438\u0431\u0438\u0442\u043d\u044b\u0435 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0438 \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u0437\u0430\u0432\u0435\u0437\u043b\u0438.<\/p>\n<\/li>\n<\/ul>\n<h2>\u0417\u0430\u0434\u0430\u0447\u0430 2. \u0412\u043e\u043b\u0448\u0435\u0431\u043d\u0430\u044f \u043f\u0430\u043b\u043e\u0447\u043a\u0430<\/h2>\n<h3>\u0423\u0441\u043b\u043e\u0432\u0438\u0435<\/h3>\n<p>\u041a\u043e\u0433\u0434\u0430 \u041d\u0435\u0437\u043d\u0430\u0438\u0306\u043a\u0430 \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u0442 \u043f\u044f\u0442\u044c \u0434\u043e\u0431\u0440\u044b\u0445 \u0434\u0435\u043b \u043f\u043e\u0434\u0440\u044f\u0434, \u043f\u043e\u044f\u0432\u0438\u0442\u0441\u044f \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u0438\u043a \u0438 \u0432\u0440\u0443\u0447\u0438\u0442 \u0435\u043c\u0443 \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u0443\u044e \u043f\u0430\u043b\u043e\u0447\u043a\u0443. <\/p>\n<p>\u041a\u043e\u0433\u0434\u0430 \u041d\u0435\u0437\u043d\u0430\u0438\u0306\u043a\u0430 \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u0442 \u043f\u044f\u0442\u044c \u043f\u043b\u043e\u0445\u0438\u0445 \u0434\u0435\u043b \u043f\u043e\u0434\u0440\u044f\u0434, \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u0438\u043a \u043e\u0442\u0431\u0435\u0440\u0435\u0442 \u0443 \u043d\u0435\u0433\u043e \u043f\u0430\u043b\u043e\u0447\u043a\u0443. <\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043f\u0430\u043b\u043e\u0447\u043a\u0443 \u0432 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0438\u0306 \u0440\u0430\u0437, \u041d\u0435\u0437\u043d\u0430\u0438\u0306\u043a\u0435 \u043f\u0440\u0438\u0434\u0435\u0442\u0441\u044f \u0441\u043e\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u043d\u0430 \u043e\u0434\u043d\u043e \u0434\u043e\u0431\u0440\u043e\u0435 \u0434\u0435\u043b\u043e \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u0432 \u043f\u0440\u043e\u0448\u043b\u044b\u0438\u0306 (\u043d\u043e \u0447\u0442\u043e\u0431\u044b \u043b\u0438\u0448\u0438\u0442\u044c\u0441\u044f \u043f\u0430\u043b\u043e\u0447\u043a\u0438, \u0432\u0441\u0435\u0433\u0434\u0430 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u044f\u0442\u0438 \u043f\u043b\u043e\u0445\u0438\u0445 \u0434\u0435\u043b \u2014 \u0442\u0430\u043a\u0430\u044f \u043d\u0435\u0441\u043f\u0440\u0430\u0432\u0435\u0434\u043b\u0438\u0432\u043e\u0441\u0442\u044c). <\/p>\n<p>\u041d\u0435\u0437\u043d\u0430\u0438\u0306\u043a\u0438\u043d\u044b \u0434\u0435\u043b\u0430 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443 deeds: <\/p>\n<pre><code class=\"pgsql\">CREATE TABLE deeds(   ts timestamp PRIMARY KEY,   good boolean NOT NULL -- t - \u0445\u043e\u0440\u043e\u0448\u0435\u0435 \u0434\u0435\u043b\u043e, f - \u043f\u043b\u043e\u0445\u043e\u0435 );<\/code><\/pre>\n<p>\u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u044b (<code>tsrange<\/code>) \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u044f \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u043e\u0438\u0306 \u043f\u0430\u043b\u043e\u0447\u043a\u043e\u0438\u0306. <\/p>\n<p><strong>\u041f\u0440\u0438\u043c\u0435\u0440 <\/strong><\/p>\n<p>\u0414\u043b\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u0445\u043e\u0434\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 <\/p>\n<pre><code class=\"pgsql\">INSERT INTO deeds VALUES   ('2024-04-01 01:00:00'::timestamp, true),   ('2024-04-01 02:00:00'::timestamp, true),   ('2024-04-01 03:00:00'::timestamp, false),   ('2024-04-01 04:00:00'::timestamp, true),   ('2024-04-01 05:00:00'::timestamp, true),   ('2024-04-01 06:00:00'::timestamp, true),   ('2024-04-01 07:00:00'::timestamp, true),   ('2024-04-01 08:00:00'::timestamp, true),   ('2024-04-01 09:00:00'::timestamp, false);<\/code><\/pre>\n<p>\u0437\u0430\u043f\u0440\u043e\u0441 \u0434\u043e\u043b\u0436\u0435\u043d \u0432\u044b\u0432\u0435\u0441\u0442\u0438: <\/p>\n<pre><code>         range ------------------------  [2024-04-01 08:00:00,) (1 rows)<\/code><\/pre>\n<h3>\u0420\u0435\u0448\u0435\u043d\u0438\u0435<\/h3>\n<p>\u0415\u0449\u0435 \u043e\u0434\u043d\u0430 \u0440\u0430\u0437\u043c\u0438\u043d\u043e\u0447\u043d\u0430\u044f \u0437\u0430\u0434\u0430\u0447\u0430 \u043d\u0430 \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u0435 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u043c\u0438 \u0438 \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u044b\u043c\u0438 \u043f\u043e\u0434\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438.<\/p>\n<p>\u0414\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e, \u0447\u0442\u043e \u043f\u0435\u0440\u0432\u043e-\u043d\u0430\u043f\u0435\u0440\u0432\u043e \u043d\u0430\u0434\u043e \u0440\u0430\u0437\u0431\u0438\u0442\u044c \u0432\u0441\u0435 \u0434\u0435\u043b\u0430 \u043d\u0430 \u0433\u0440\u0443\u043f\u043f\u044b <em>\u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u044b\u0445 \u043f\u043e\u0434\u0440\u044f\u0434 \u0438\u0434\u0443\u0449\u0438\u0445<\/em>. \u042d\u0442\u043e \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"pgsql\">WITH prev AS ( -- \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0435 \u0434\u0435\u043b\u043e   SELECT ts, good, lag(good) OVER (ORDER BY ts) prev_good    FROM deeds ), changes AS ( -- \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u044b \u0438\u0437 \u043e\u0434\u043d\u043e\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432 \u0434\u0440\u0443\u0433\u043e\u0435   SELECT ts, good, prev_good, CASE WHEN good != prev_good THEN 1 END change   FROM prev ) -- \u043f\u043e\u0434\u0441\u0447\u0435\u0442 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u043e\u0432 \u043d\u0430\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0438\u043c \u0438\u0442\u043e\u0433\u043e\u043c \u0434\u0430\u0435\u0442 \u043d\u043e\u043c\u0435\u0440\u0430 \u0433\u0440\u0443\u043f\u043f SELECT ts, good, prev_good, change, count( change ) OVER (ORDER BY ts) grp  FROM changes ORDER BY ts;<\/code><\/pre>\n<pre><code>         ts          | good | prev_good | change | grp  ---------------------+------+-----------+--------+-----  2024-04-01 01:00:00 | t    |           |        |   0  2024-04-01 02:00:00 | t    | t         |        |   0  2024-04-01 03:00:00 | f    | t         |      1 |   1  2024-04-01 04:00:00 | t    | f         |      1 |   2  2024-04-01 05:00:00 | t    | t         |        |   2  2024-04-01 06:00:00 | t    | t         |        |   2  2024-04-01 07:00:00 | t    | t         |        |   2  2024-04-01 08:00:00 | t    | t         |        |   2  2024-04-01 09:00:00 | f    | t         |      1 |   3 (9 rows)<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043c\u044b \u043c\u043e\u0436\u0435\u043c \u043f\u043e\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043d\u0430\u0440\u0430\u0441\u0442\u0430\u044e\u0449\u0438\u043c \u0438\u0442\u043e\u0433\u043e\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0434\u0435\u043b \u0432 \u043a\u0430\u0436\u0434\u043e\u0439 \u0433\u0440\u0443\u043f\u043f\u0435: \u0443\u0434\u043e\u0431\u043d\u043e \u0432\u0437\u044f\u0442\u044c \u0445\u043e\u0440\u043e\u0448\u0438\u0435 \u0434\u0435\u043b\u0430 \u0441 \u043f\u043b\u044e\u0441\u043e\u043c, \u0430 \u043f\u043b\u043e\u0445\u0438\u0435 \u2014 \u0441 \u043c\u0438\u043d\u0443\u0441\u043e\u043c.<\/p>\n<pre><code class=\"pgsql\">WITH grps AS (   -- \u044d\u0442\u043e \u043c\u044b \u0443\u0436\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u0432\u044b\u0448\u0435, \u043d\u043e \u0442\u0443\u0442 +1\/-1 \u0432\u043c\u0435\u0441\u0442\u043e boolean   SELECT ts,      CASE WHEN good THEN 1 ELSE -1 END grade,      count( change ) OVER (ORDER BY ts) grp    FROM (     SELECT ts, good,        CASE WHEN good != lag(good) OVER (ORDER BY ts) THEN 1 END change      FROM deeds   ) ) SELECT ts, grade, grp, sum(grade) OVER (PARTITION BY grp ORDER BY ts)  FROM grps ORDER BY ts; <\/code><\/pre>\n<pre><code>         ts          | grade | grp | sum  ---------------------+-------+-----+-----  2024-04-01 01:00:00 |     1 |   0 |   1  2024-04-01 02:00:00 |     1 |   0 |   2  2024-04-01 03:00:00 |    -1 |   1 |  -1  2024-04-01 04:00:00 |     1 |   2 |   1  2024-04-01 05:00:00 |     1 |   2 |   2  2024-04-01 06:00:00 |     1 |   2 |   3  2024-04-01 07:00:00 |     1 |   2 |   4  2024-04-01 08:00:00 |     1 |   2 |   5  2024-04-01 09:00:00 |    -1 |   3 |  -1 (9 rows)<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u0435\u0442\u0441\u044f \u0432\u0437\u044f\u0442\u044c \u043f\u0435\u0440\u0432\u0443\u044e \u043f\u043e \u043f\u043e\u0440\u044f\u0434\u043a\u0443 5-\u043a\u0443, \u0437\u0430\u0442\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0437\u0430 \u043d\u0435\u0439 -5, \u0437\u0430\u0442\u0435\u043c 6, -5, 7 \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u042d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430 \u0434\u043b\u044f \u0440\u0435\u043a\u0443\u0440\u0441\u0438\u0432\u043d\u043e\u0433\u043e (\u0447\u0438\u0442\u0430\u0439, \u0438\u0442\u0435\u0440\u0430\u0442\u0438\u0432\u043d\u043e\u0433\u043e) \u0437\u0430\u043f\u0440\u043e\u0441\u0430. \u041d\u0443 \u0438 \u043d\u0430\u0434\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u043a\u043b\u0435\u0438\u0442\u044c \u043f\u0430\u0440\u044b \u0441\u0442\u0440\u043e\u043a, \u0438\u0434\u0443\u0449\u0438\u0445 \u0434\u0440\u0443\u0433 \u0437\u0430 \u0434\u0440\u0443\u0433\u043e\u043c, \u0432 \u043e\u0434\u0438\u043d \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d, \u043a\u0430\u043a \u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0432 \u0443\u0441\u043b\u043e\u0432\u0438\u0438.<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u043e\u043b\u043d\u043e\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u0435<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"pgsql\">WITH RECURSIVE grps AS (    SELECT ts,      CASE WHEN good THEN 1 ELSE -1 END grade,      count( change ) OVER (ORDER BY ts) grp    FROM (     SELECT ts, good,        CASE WHEN good != lag(good) OVER (ORDER BY ts) THEN 1 END change      FROM deeds   ) ), s AS (   SELECT ts, sum(grade) OVER (PARTITION BY grp ORDER BY ts) score   FROM grps ), r AS (    -- \u0432\u044b\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u043e\u0435 \u0434\u043e\u0441\u0442\u0438\u0436\u0435\u043d\u0438\u0435 \u043f\u044f\u0442\u0435\u0440\u043a\u0438...   (SELECT ts, score,       score+0.5 AS score_plus -- \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u043c \u043f\u043e 0.5, \u0447\u0442\u043e\u0431\u044b \u043e\u0442\u0440\u0430\u0441\u0442\u0430\u043b\u043e \u0437\u0430 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430    FROM s    WHERE score = 5     ORDER BY ts LIMIT 1   )   UNION ALL    -- ...\u0437\u0430\u0442\u0435\u043c -5, 6, -5, 7 \u0438 \u0442. \u0434., \u0447\u0435\u0440\u0435\u0434\u0443\u0435\u043c \u0437\u043d\u0430\u043a   (SELECT s.ts, s.score, r.score_plus+0.5     FROM s CROSS JOIN r    WHERE s.ts > r.ts       AND s.score = CASE WHEN r.score > 0 THEN -5 ELSE r.score_plus END     ORDER BY<\/code><\/pre>\n<\/div>\n<\/details>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-373834","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/373834","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=373834"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/373834\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=373834"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=373834"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=373834"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}