{"id":385726,"date":"2024-06-29T06:16:53","date_gmt":"2024-06-29T06:16:53","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=385726"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=385726","title":{"rendered":"<span>SQL \u043d\u0430 \u0441\u0442\u0435\u0440\u043e\u0438\u0434\u0430\u0445 \u2013 5 \u043a\u0435\u0439\u0441\u043e\u0432 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f dbt + Jinja<\/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<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/169\/8a4\/3f8\/1698a43f8fcdebe51d6980b0d67be997.png\" width=\"780\" height=\"439\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/169\/8a4\/3f8\/1698a43f8fcdebe51d6980b0d67be997.png\"\/><figcaption><\/figcaption><\/figure>\n<p>SQL \u2013 \u044d\u0442\u043e \u043d\u0435\u0441\u043a\u0443\u0447\u043d\u043e. \u0421 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u044f\u0437\u044b\u043a\u0430 \u043a\u0440\u0430\u0442\u043d\u043e \u0432\u043e\u0437\u0440\u043e\u0441\u043b\u0438. \u041c\u0443\u043b\u044c\u0442\u0438\u0442\u0443\u043b \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 <a href=\"https:\/\/habr.com\/ru\/company\/wheely\/blog\/549614\/\"><u>dbt<\/u><\/a>, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043e\u0447\u043d\u044b\u0435 <a href=\"https:\/\/habr.com\/ru\/company\/wheely\/blog\/539154\/\"><u>\u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0421\u0423\u0411\u0414<\/u><\/a> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0442\u0432\u043e\u0440\u0438\u0442\u044c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0447\u0443\u0434\u0435\u0441\u0430.<\/p>\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u0440\u0442\u0435\u043c\u0438\u0439 \u0438 \u044f <em>Analytics Engineer<\/em>. \u0418 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043b \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u044d\u043a\u0441\u043a\u0443\u0440\u0441 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0433\u0438\u0431\u0440\u0438\u0434\u043d\u043e\u0433\u043e SQL:<\/p>\n<ul>\n<li>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 Pivot \u0438 Unpivot \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0443\u0440\u0440\u043e\u0433\u0430\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0438 \u043a\u043b\u044e\u0447\u0430 \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u0413\u0438\u0431\u043a\u0430\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432 S3<\/p>\n<\/li>\n<li>\n<p>\u0412\u0430\u043b\u044e\u0442\u043d\u044b\u0435 \u043a\u0443\u0440\u0441\u044b, Continuous Integration, Data Quality<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 Pivot \u0438 Unpivot \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f <em>pivot<\/em> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u043b\u043e\u0441\u043a\u0443\u044e \u0434\u0432\u0443\u043c\u0435\u0440\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442 \u043d\u043e\u0432\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438. \u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f <em>unpivot<\/em> \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0432 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0432 \u0441\u0442\u0440\u043e\u043a\u0438. \u0418\u043d\u0430\u0447\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u044f\u043c\u0438 \u0441\u043e \u0441\u0432\u043e\u0434\u043d\u044b\u043c\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c\u0438 (<em>\u0441ross-tables<\/em>).<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u044d\u0442\u043e \u043d\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"markdown\">Input: orders  | size | color | |------|-------| | S    | red   | | S    | blue  | | S    | red   | | M    | red   |   Pivot output:  | size | red | blue | |------|-----|------| | S    | 2   | 1    | | M    | 1   | 0    |  --------------  Input: orders  | date       | size | color | status     | |------------|------|-------|------------| | 2017-01-01 | S    | red   | complete   | | 2017-03-01 | S    | red   | processing |   Unpivot output:  | date       | status     | field_name | value | |------------|------------|------------|-------| | 2017-01-01 | complete   | size       | S     | | 2017-01-01 | complete   | color      | red   | | 2017-03-01 | processing | size       | S     | | 2017-03-01 | processing | color      | red   |<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u044b dbt, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 SQL, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u0433\u0438\u0431\u043a\u043e \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430, \u0431\u0435\u0437 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0439 \u0421\u0423\u0411\u0414.<\/p>\n<p>\u0420\u0435\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u2013 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043e\u0433\u043e\u0432\u043e\u0440\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/93d\/107\/40e\/93d10740e882f72703be0b6ec288f586.png\" width=\"492\" height=\"342\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/93d\/107\/40e\/93d10740e882f72703be0b6ec288f586.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/a70\/692\/ce1\/a70692ce11dd90801330e662ce18c316.png\" width=\"651\" height=\"298\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/a70\/692\/ce1\/a70692ce11dd90801330e662ce18c316.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041c\u0430\u043a\u0440\u043e\u0441, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0432 SQL-\u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<pre><code class=\"sql\">{{ dbt_utils.unpivot(  \u00a0relation=ref('dim_chauffeurs_labels'),  \u00a0cast_to='varchar',  \u00a0exclude=['actual_dt', 'chauffeur_id'],  \u00a0field_name='label',  \u00a0value_name='value'  ) }}<\/code><\/pre>\n<p>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u044b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c, \u044d\u0442\u043e \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0438 \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434, \u0447\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e.<\/p>\n<h3>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0443\u0440\u0440\u043e\u0433\u0430\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0438 \u043a\u043b\u044e\u0447\u0430 \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0443\u0440\u0440\u043e\u0433\u0430\u0442\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u2013 \u0432\u0430\u0436\u043d\u0435\u0439\u0448\u0438\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u043b\u044e\u0431\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u042d\u0442\u043e \u043a\u043b\u044e\u0447\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0435 \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0444\u0430\u043a\u0442\u043e\u0432 \u0438 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0439. \u041e\u0431\u044b\u0447\u043d\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0445\u044d\u0448-\u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u043e\u0434\u0430\u0432\u0430\u044f \u043d\u0430 \u0432\u0445\u043e\u0434 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043a\u043b\u044e\u0447\u0435\u0439 \u0438\u0437 \u0441\u0438\u0441\u0442\u0435\u043c-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432. \u042d\u0442\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u0442\u0430\u043a\u0436\u0435 \u0448\u0438\u0440\u043e\u043a\u043e \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0430 \u0432 Data Vault 2.0 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043c\u0435\u0436\u0434\u0443 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432.<\/p>\n<p>\u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0432\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c (<em>human-readable<\/em>) \u0432\u0441\u0435\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0432 \u043c\u0430\u0440\u043a\u0435\u0442\u0438\u043d\u0433\u043e\u0432\u043e\u0439 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0435, \u0433\u0434\u0435 \u043a\u043b\u044e\u0447 \u0441\u0442\u0440\u043e\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u043c\u0435\u0442\u043e\u043a: <em>utm_source<\/em>, <em>utm_medium<\/em>, <em>utm_campaign<\/em>, <em>ads_group_id<\/em>, <em>keyword_id<\/em>.\u00a0<\/p>\n<p>\u0423\u0434\u043e\u0431\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0435 (<em>human-readable<\/em>) \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0431\u0430\u0433\u0438, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0445\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0440\u0440\u043e\u0433\u0430\u0442\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0442\u0430\u0431\u043b\u0438\u0446:<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/83c\/4af\/a57\/83c4afa57331256b68737a9147b25dba.png\" width=\"1116\" height=\"326\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/83c\/4af\/a57\/83c4afa57331256b68737a9147b25dba.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u044d\u0442\u0438\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 <a href=\"https:\/\/github.com\/kzzzr\/mybi-dbt-core\/blob\/master\/macros\/surrogate_key.sql\"><u>hash(), concat(), surrogate_key()<\/u><\/a> (\u0430\u0434\u0430\u043f\u0442\u0435\u0440 MS SQL):<\/p>\n<details class=\"spoiler\">\n<summary>hash(), concat(), surrogate_key() macros<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"sql\">------------------------  --- MSSQL hash macro ---  ------------------------  {% macro hash(field) -%}  \u00a0\u00a0\u00a0HASHBYTES('SHA2_256', {{field}})  {%- endmacro %}  \u00a0  --------------------------  --- MSSQL concat macro ---  --------------------------  {% macro concat(fields) -%}  \u00a0\u00a0\u00a0concat({{ fields|join(', ') }})  {%- endmacro %}  \u00a0  \u00a0  --------------------------  --- Surrogate hash key ---  --------------------------  {%- macro surrogate_key(field_list) -%}  \u00a0  \u00a0\u00a0\u00a0{%- if varargs|length >= 1 %}  \u00a0  \u00a0\u00a0\u00a0{%- do exceptions.warn(\"Warning: the `surrogate_key` macro now takes a single list argument instead of multiple string arguments. Support for multiple string arguments will be deprecated in a future release of dbt-utils.\") -%}  \u00a0  \u00a0\u00a0\u00a0{# first argument is not included in varargs, so add first element to field_list_xf #}  \u00a0\u00a0\u00a0{%- set field_list_xf = [field_list] -%}  \u00a0  \u00a0\u00a0\u00a0{%- for field in varargs %}  \u00a0\u00a0\u00a0{%- set _ = field_list_xf.append(field) -%}  \u00a0\u00a0\u00a0{%- endfor -%}  \u00a0  \u00a0\u00a0\u00a0{%- else -%}  \u00a0  \u00a0\u00a0\u00a0{# if using list, just set field_list_xf as field_list #}  \u00a0\u00a0\u00a0{%- set field_list_xf = field_list -%}  \u00a0  \u00a0\u00a0\u00a0{%- endif -%}  \u00a0  \u00a0  \u00a0\u00a0\u00a0{%- set fields = [] -%}  \u00a0  \u00a0\u00a0\u00a0{%- for field in field_list_xf -%}  \u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- set _ = fields.append(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"coalesce(cast(\" ~ field ~ \" as NVARCHAR \" ~ \"), '')\"  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0) -%}  \u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- if not loop.last %}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- set _ = fields.append(\"'-'\") -%}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- endif -%}  \u00a0  \u00a0\u00a0\u00a0{%- endfor -%}  \u00a0  \u00a0\u00a0\u00a0{# {{ concat(fields) }} #}  \u00a0\u00a0\u00a0{{ mybi_dbt_core.hash(mybi_dbt_core.concat(fields)) }}  \u00a0  {%- endmacro -%}<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0441\u043e\u0431\u043e\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u0443\u044e \u0444\u043e\u0440\u043c\u0443<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 <em>null,<\/em> \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0432\u044b\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043a\u043b\u044e\u0447\u0430<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f \u043c\u0435\u0436\u0434\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u043a\u043b\u044e\u0447\u0430 (\u0442\u0438\u0440\u0435, \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u043b\u044e\u0431\u043e\u0433\u043e \u0434\u0440\u0443\u0433\u043e\u0433\u043e)<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b\u0437\u043e\u0432 \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 \u0432 \u043a\u043e\u0434\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"sql\">select    {{ surrogate_key([\"dt\", \"campaign_id\", \"ads_id\"]) }} as hash_key   , {{ concat_key([\"dt\", \"campaign_id\", \"ads_id\"]) }} as concat_key<\/code><\/pre>\n<p>\u0410\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0432 \u0421\u0423\u0411\u0414 (\u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f):<\/p>\n<pre><code class=\"sql\">select    HASHBYTES('SHA2_256', concat(coalesce(cast([dt] as NVARCHAR ), ''), '-', coalesce(cast([campaign_id] as NVARCHAR ), ''), '-', coalesce(cast([ads_id] as NVARCHAR ), ''))) as hash_key , concat(coalesce(cast([dt] as NVARCHAR ), ''), '-', coalesce(cast([campaign_id] as NVARCHAR ), ''), '-', coalesce(cast([ads_id] as NVARCHAR ), '')) as concat_key<\/code><\/pre>\n<h3>\u0413\u0438\u0431\u043a\u0430\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432<\/h3>\n<p>\u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0414\u0430\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432 \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u0441\u043e\u0442\u0435\u043d \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0441\u0432\u043e\u0438\u043c\u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0438\u043c\u0435\u0435\u0442 \u0441\u043c\u044b\u0441\u043b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043a\u0438, \u043e\u0431\u0440\u0430\u0449\u0430\u044f\u0441\u044c \u043a \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u0434\u0430\u043d\u043d\u044b\u043c.<\/p>\n<p>\u0418\u043c\u0435\u0439\u0442\u0435 \u0432 \u0432\u0438\u0434\u0443 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438:<\/p>\n<ul>\n<li>\n<p>\u0427\u0442\u0435\u043d\u0438\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (<em>deleted_flag is not true<\/em>)<\/p>\n<\/li>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0439 \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 Continuous Integration<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0438\u0441\u043a \u0434\u0435\u043b\u044c\u0442\u044b \u0434\u043b\u044f \u0438\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432\u0438\u0442\u0440\u0438\u043d<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043b\u043e\u043d\u043e\u043a, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u043a \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0443. \u0420\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u043c\u043e\u0433\u0443\u0442 \u0442\u0430\u043a\u0436\u0435 \u0438 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u2013 <em>epoch<\/em> (bigint) vs <em>timestamp<\/em>.<\/p>\n<p>\u0412\u0441\u0435 \u044d\u0442\u0438 \u0432\u0432\u043e\u0434\u043d\u044b\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u043b\u043e\u0436\u0430\u0442\u0441\u044f \u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 <em>WHERE<\/em>.<\/p>\n<pre><code class=\"sql\">select  \u00a0\u00a0\u00a0...  from {{ source('backend', 'orders') }}  {{ hevo_filter_rows( \u00a0\u00a0\u00a0deleted_rows_filter=true, \u00a0\u00a0\u00a0last_n_days_of_data=false, \u00a0\u00a0\u00a0timestamp_column='created_at', \u00a0\u00a0\u00a0incremental_column='__metadata_timestamp'\u00a0\u00a0\u00a0 ) }}<\/code><\/pre>\n<p>\u0421\u0430\u043c \u043c\u0430\u043a\u0440\u043e\u0441 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c (\u0441 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f\u043c\u0438):<\/p>\n<details class=\"spoiler\">\n<summary>macro hevo_filter_rows()<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"sql\">-- filter data for deleted rows; resize for dev, ci pipelines; apply incremental load filters  {% macro hevo_filter_rows(  \u00a0\u00a0\u00a0deleted_rows_filter=true,  \u00a0\u00a0\u00a0last_n_days_of_data=false,  \u00a0\u00a0\u00a0timestamp_column='created_at',  \u00a0\u00a0\u00a0incremental_column='__metadata_timestamp'  ) -%}  \u00a0\u00a0  \u00a0\u00a0\u00a0{#- prepare expression to filter deleted rows by flag __hevo__marked_deleted where it exists\u00a0 -#}  \u00a0\u00a0\u00a0{%- set deleted_rows_expression = '__hevo__marked_deleted is not true' if deleted_rows_filter == true else '1 = 1' -%}  \u00a0  \u00a0\u00a0\u00a0{#- cast epoch to timestamp if necessary -#}  \u00a0\u00a0\u00a0{%- set timestamp_column = epoch_to_timestamp('__hevo__ingested_at')  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if timestamp_column == '__hevo__ingested_at' else timestamp_column -%}  \u00a0  \u00a0\u00a0\u00a0{#- prepare expression to filter rows to last 'development_days_of_data' (e.g. last 3 days) -#}\u00a0\u00a0  \u00a0\u00a0\u00a0{% set get_dev_watermark_query = 'select dateadd(day, ' ~ -1 * var('development_days_of_data') ~ ', current_timestamp::date)' %}  \u00a0\u00a0\u00a0{# {{ log(\"get_dev_watermark_query: \" ~ get_dev_watermark_query, info=True) }} #}  \u00a0\u00a0\u00a0{% if execute %}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{% set dev_watermark = \"'\" ~ run_query(get_dev_watermark_query).columns[0][0] ~ \"'\" %}  \u00a0\u00a0\u00a0{% endif %}\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  \u00a0\u00a0\u00a0{%- set dev_rows_expression = timestamp_column ~ ' >= ' ~ dev_watermark  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if target.name in ['dev', 'ci'] and last_n_days_of_data == true else '1 = 1' -%}  \u00a0  \u00a0\u00a0\u00a0{#- prepare expression to filter only delta rows on incremental build -#}  \u00a0\u00a0\u00a0{%- set incremental_expression =  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0epoch_to_timestamp('__hevo__ingested_at') ~ '  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0>= dateadd(h, -24, (select max(' ~ incremental_column ~ ') from ' ~ this ~ '))'  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if is_incremental() else '1 = 1' -%}  \u00a0  \u00a0\u00a0\u00a0{#- prepare final filter expression -#}  \u00a0\u00a0\u00a0where 1 = 1  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0and {{ deleted_rows_expression }}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0and {{ dev_rows_expression }}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0and {{ incremental_expression }}  \u00a0  {%- endmacro -%}<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u043b\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e (\u0441 \u043d\u0443\u043b\u044f) \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0432 dev-\u043a\u043e\u043d\u0442\u0443\u0440\u0435:<\/p>\n<pre><code class=\"sql\">select\u00a0  \u00a0\u00a0\u00a0...  from {{ source('backend', 'orders') }}  where 1 = 1 \u00a0\u00a0\u00a0and __hevo__marked_deleted is not true \u00a0\u00a0\u00a0and created_at >= '2021-08-10 00:00:00' \u00a0\u00a0\u00a0and 1 = 1<\/code><\/pre>\n<p>\u00a0<\/p>\n<h3>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432 S3<\/h3>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u0433\u0434\u0435 \u043c\u044b \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043b\u0438 unpivot-\u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u043e\u043d\u0438 \u043e\u0431\u0440\u0430\u0442\u0438\u043b\u0438\u0441\u044c \u043a \u043d\u0430\u043c \u0441 \u043f\u0440\u043e\u0441\u044c\u0431\u043e\u0439 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043d\u043e \u043a\u0430\u043a \u043f\u043b\u043e\u0441\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 Object Storage (S3).<\/p>\n<p>\u0412\u043f\u043e\u043b\u043d\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439. \u041c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u0434\u0443\u043c\u0430\u0442\u044c \u043e\u0431 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u0432\u044b\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b, \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u044f\u0437\u044b\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u043e <em>\u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0431\u0435\u0437 \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043d\u0430 \u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438<\/em>. \u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u0443\u043c\u0435\u0435\u0442 \u0441\u0430\u043c\u0430 \u0421\u0423\u0411\u0414.<\/p>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f UNLOAD (\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 Amazon Redshift), \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0430\u044f \u043a\u0430\u043a <em>post-hook <\/em>\u043c\u043e\u0434\u0435\u043b\u0438 dbt:<\/p>\n<details class=\"spoiler\">\n<summary>UNLOAD to S3<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"sql\">{{ \u00a0\u00a0\u00a0config( \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0materialized='view', \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0post_hook=[ \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- if target.name == 'prod' -%} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0UNLOAD ('SELECT actual_dt, chauffeur_id, label, value FROM {{ this.schema }}.{{ this.table }} ORDER BY actual_dt, chauffeur_id') \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0TO 's3:\/\/my-analytics-bucket\/dwh\/unload\/chauffeurs_labels' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0IAM_ROLE 'arn:aws:iam::88002000000:role\/redshift-role' \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0FORMAT AS CSV \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0PARTITION BY (actual_dt) INCLUDE \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0HEADER \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0CLEANPATH \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- endif -%} \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\" \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0]\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 \u00a0\u00a0\u00a0) }} \u00a0  {{ dbt_utils.unpivot( \u00a0relation=ref('dim_chauffeurs_labels'), \u00a0cast_to='varchar', \u00a0exclude=['actual_dt', 'chauffeur_id'], \u00a0field_name='label', \u00a0value_name='value' ) }}<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0422\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u043d\u0430 \u043a\u0430\u0436\u0434\u044b\u0439 \u0440\u0435\u0433\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0440\u0430\u0441\u0447\u0435\u0442 (\u0440\u0430\u0437 \u0432 \u0441\u0443\u0442\u043a\u0438, \u0440\u0430\u0437 \u0432 \u0447\u0430\u0441) \u0431\u0443\u0434\u0435\u0442 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u0438 \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0430 \u0432 S3 \u043f\u043e \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u043e\u043c\u0443 \u043f\u0443\u0442\u0438 csv-\u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0430. \u0410 \u0447\u0442\u043e\u0431\u044b \u043d\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0434\u0430\u043d\u043d\u044b\u0435 \u0432 \u0421\u0423\u0411\u0414, \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0443 \u043a\u0430\u043a \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 (view, \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0430\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u0430).<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/94b\/2bb\/32f\/94b2bb32fb26d906d4b6e1f9e849d2b7.png\" width=\"1600\" height=\"575\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/94b\/2bb\/32f\/94b2bb32fb26d906d4b6e1f9e849d2b7.png\"\/><figcaption><\/figcaption><\/figure>\n<p>8 \u0444\u0430\u0439\u043b\u043e\u0432 \u043f\u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0443 \u0443\u0437\u043b\u043e\u0432 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u0435 (\u043f\u0440\u0438\u043d\u0446\u0438\u043f MPP-\u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445)<\/p>\n<h3>\u0415\u0449\u0435 \u0431\u043e\u043b\u044c\u0448\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432<\/h3>\n<p>\u0420\u0430\u043d\u0435\u0435 \u044f \u043f\u0438\u0441\u0430\u043b \u043e \u0434\u0440\u0443\u0433\u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0445 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u044f\u0445 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e\u0433\u043e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0433\u043e \u0441\u0442\u0435\u043a\u0430:<\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/567916\/\"><u>\u0418\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0442\u0435\u0441\u0442\u044b \u0434\u043b\u044f \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0414\u0430\u043d\u043d\u044b\u0445 \u2013 \u041d\u0430\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c Slim CI \u0434\u043b\u044f DWH<\/u><\/a><\/p>\n<ul>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u044f \u0434\u043b\u044f CI<\/p>\n<\/li>\n<li>\n<p>\u0413\u0438\u0431\u043a\u043e\u0435 \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0441\u0445\u0435\u043c\u043e\u0439, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u0430 Pull Request<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/558238\/\"><u>\u041a\u0443\u0440\u0441\u044b \u0432\u0430\u043b\u044e\u0442 \u0438 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0430 \u2013 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0431\u043c\u0435\u043d\u043d\u044b\u0445 \u043a\u0443\u0440\u0441\u043e\u0432 \u0432 \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0414\u0430\u043d\u043d\u044b\u0445<\/u><\/a><\/p>\n<ul>\n<li>\n<p>\u041c\u0430\u043a\u0440\u043e\u0441\u044b \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c\u0438 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 (External Tables)<\/p>\n<\/li>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u043f\u0435\u0440\u0435\u0441\u0447\u0435\u0442\u0430 \u043a\u0443\u0440\u0441\u043e\u0432 \u0432\u0430\u043b\u044e\u0442 \u043d\u0430 \u043b\u0435\u0442\u0443<\/p>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/habr.com\/ru\/company\/otus\/blog\/526174\/\"><u>\u200b\u200b\u041a\u0442\u043e \u043e\u0442\u0432\u0435\u0442\u0438\u0442 \u0437\u0430 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438: QA \u0434\u043b\u044f \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0414\u0430\u043d\u043d\u044b\u0445<\/u><\/a><\/p>\n<ul>\n<li>\n<p>\u0422\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0436\u0438\u0434\u0430\u043d\u0438\u0439 (expectations) \u043e\u0442 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0443<\/p>\n<\/li>\n<\/ul>\n<h3>\u041f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u043d\u0430\u0432\u044b\u043a\u0438 \u0438 \u0436\u0438\u0432\u043e\u0435 \u043e\u0431\u0449\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041c\u0435\u0436\u0434\u0443 \u0442\u0435\u043c, \u0435\u0441\u043b\u0438 \u0432\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u0435\u043d\u0438\u0435, \u043d\u043e \u0438 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u0432\u043a\u0443\u043f\u0435 \u0441 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435\u043c \u0437\u043d\u0430\u043d\u0438\u0439 \u0438\u0437 \u043f\u0435\u0440\u0432\u044b\u0445 \u0443\u0441\u0442, \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u044c\u0442\u0435\u0441\u044c \u0441 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u043e\u0439 \u041e\u0422\u0423\u0421 \u0438 \u0437\u0430\u043d\u044f\u0442\u0438\u044f\u043c\u0438, \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u044f \u0438 \u043c\u043e\u0438 \u043a\u043e\u043b\u043b\u0435\u0433\u0438 \u0434\u0435\u043b\u0438\u043c\u0441\u044f \u0432\u0441\u0435\u0445 \u0442\u0435\u043c, \u0447\u0442\u043e \u0443\u043c\u0435\u0435\u043c \u0438 \u043b\u044e\u0431\u0438\u043c \u0434\u0435\u043b\u0430\u0442\u044c.<\/p>\n<p><a href=\"https:\/\/otus.ru\/lessons\/data-engineer\/\"><em><u>Data Engineer<\/u><\/em><\/a> \u2013 \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u0445 \u0442\u0438\u0440\u0430\u0436\u043d\u044b\u0445 \u043a\u0443\u0440\u0441\u043e\u0432, \u0432 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0445 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u044f \u0443\u0447\u0430\u0441\u0442\u0432\u0443\u044e \u0443\u0436\u0435 \u0431\u043e\u043b\u0435\u0435 2-\u0445 \u043b\u0435\u0442. \u041a \u043d\u043e\u0432\u043e\u043c\u0443 \u0441\u0442\u0430\u0440\u0442\u0443 \u0433\u043e\u0442\u043e\u0432\u044b \u043a\u0430\u0440\u0434\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u044e, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c, \u0438\u043d\u0444\u0440\u0430\u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435, \u0432\u043a\u043b\u044e\u0447\u0430\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0435 \u0432\u0435\u0431\u0438\u043d\u0430\u0440\u044b \u043d\u0430 \u0440\u0430\u0437\u0431\u043e\u0440 \u0434\u043e\u043c\u0430\u0448\u043d\u0438\u0445 \u0437\u0430\u0434\u0430\u043d\u0438\u0439.<\/p>\n<p><a href=\"https:\/\/otus.ru\/lessons\/dwh\/\"><em><u>Analytics Engineer<\/u><\/em><\/a> \u2013 \u043f\u043e\u043f\u044b\u0442\u043a\u0430 \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u043f\u043e\u0442\u0440\u0435\u0431\u043d\u043e\u0441\u0442\u044c \u043d\u0430 \u043b\u044e\u0434\u0435\u0439-\u043c\u0443\u043b\u044c\u0442\u0438\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043b\u0438\u0441\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0438\u043b\u044c\u043d\u044b \u0438 \u0432 \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u0438 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0438 \u0431\u0438\u0437\u043d\u0435\u0441\u0430, \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u0438 \u0432 \u0438\u043d\u0436\u0435\u043d\u0435\u0440\u043d\u043e\u0439 \u0447\u0430\u0441\u0442\u0438. \u041b\u044c\u0432\u0438\u043d\u0430\u044f \u0434\u043e\u043b\u044f \u043a\u0443\u0440\u0441\u0430 \u043f\u043e\u0441\u0432\u044f\u0449\u0435\u043d\u0430 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u043c \u0421\u0423\u0411\u0414, BI-\u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c, \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430\u043c \u043f\u0440\u043e\u0434\u0432\u0438\u043d\u0443\u0442\u043e\u0439 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0438 \u0438 \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 dbt.<\/p>\n<p>\u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435!<\/p>\n<hr\/>\n<blockquote>\n<p><em>\u041c\u0430\u0442\u0435\u0440\u0438\u0430\u043b \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043b\u0435\u043d \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 \u043a\u0443\u0440\u0441\u0430 <\/em><a href=\"https:\/\/otus.pw\/GG8u\/\"><em>Data Engineer.<\/em><\/a><em> \u0415\u0441\u043b\u0438 \u0432\u0430\u0441 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0440\u0430\u0437\u0432\u0438\u0442\u0438\u0435 \u0432 \u0441\u0444\u0435\u0440\u0435 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0441 \u043d\u0443\u043b\u044f \u0434\u043e Pro, \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043f\u0440\u043e <\/em><a href=\"https:\/\/otus.pw\/ovMk\/\"><em>\u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044e Data Engineer<\/em><\/a><em>.<\/p>\n<p>\u0422\u0430\u043a\u0436\u0435 \u043f\u0440\u0438\u0433\u043b\u0430\u0448\u0430\u0435\u043c \u0432\u0441\u0435\u0445 \u0436\u0435\u043b\u0430\u044e\u0449\u0438\u0445 \u043d\u0430 Demo-\u0443\u0440\u043e\u043a \u00ab\u0412\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0432 \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u044e\u00bb. \u041d\u0430 \u044d\u0442\u043e\u043c \u0437\u0430\u043d\u044f\u0442\u0438\u0438 \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0440\u0430\u0437\u0431\u0435\u0440\u0435\u043c, \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c\u044b \u043e\u0440\u043a\u0435\u0441\u0442\u0440\u0430\u0446\u0438\u0438, \u043a\u0430\u043a\u0438\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0435\u0441\u0442\u044c \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u043d\u0430 \u0440\u044b\u043d\u043a\u0435 \u0438 \u0434\u0430\u0436\u0435 \u0443\u0433\u043b\u0443\u0431\u0438\u043c\u0441\u044f \u0432 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0434\u043d\u043e\u0439 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u043d\u044b\u0445 \u043f\u043b\u0430\u0442\u0444\u043e\u0440\u043c \u043d\u0430 \u0441\u0435\u0433\u043e\u0434\u043d\u044f: Apache Airflow.<\/em><a href=\"https:\/\/otus.pw\/GnvW\/\"> <\/a><\/p>\n<p><strong>\u2192 <\/strong><a href=\"https:\/\/otus.pw\/GnvW\/\"><strong> \u0420\u0415\u0413\u0418\u0421\u0422\u0420\u0410\u0426\u0418\u042f<\/strong><\/a><\/p>\n<\/blockquote>\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\/572816\/\"> https:\/\/habr.com\/ru\/articles\/572816\/<\/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<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>SQL \u2013 \u044d\u0442\u043e \u043d\u0435\u0441\u043a\u0443\u0447\u043d\u043e. \u0421 \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u043c\u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u043c\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u044f\u0437\u044b\u043a\u0430 \u043a\u0440\u0430\u0442\u043d\u043e \u0432\u043e\u0437\u0440\u043e\u0441\u043b\u0438. \u041c\u0443\u043b\u044c\u0442\u0438\u0442\u0443\u043b \u0434\u043b\u044f \u043c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 <a href=\"https:\/\/habr.com\/ru\/company\/wheely\/blog\/549614\/\"><u>dbt<\/u><\/a>, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043e\u0447\u043d\u044b\u0435 <a href=\"https:\/\/habr.com\/ru\/company\/wheely\/blog\/539154\/\"><u>\u0430\u043d\u0430\u043b\u0438\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0435 \u0421\u0423\u0411\u0414<\/u><\/a> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0431\u0443\u043a\u0432\u0430\u043b\u044c\u043d\u043e \u0442\u0432\u043e\u0440\u0438\u0442\u044c \u0441 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0447\u0443\u0434\u0435\u0441\u0430.<\/p>\n<p>\u041c\u0435\u043d\u044f \u0437\u043e\u0432\u0443\u0442 \u0410\u0440\u0442\u0435\u043c\u0438\u0439 \u0438 \u044f <em>Analytics Engineer<\/em>. \u0418 \u0441\u0435\u0433\u043e\u0434\u043d\u044f \u044f \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u0438\u043b \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0439 \u044d\u043a\u0441\u043a\u0443\u0440\u0441 \u0432 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0438 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u044b\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0433\u0438\u0431\u0440\u0438\u0434\u043d\u043e\u0433\u043e SQL:<\/p>\n<ul>\n<li>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 Pivot \u0438 Unpivot \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/p>\n<\/li>\n<li>\n<p>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0443\u0440\u0440\u043e\u0433\u0430\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0438 \u043a\u043b\u044e\u0447\u0430 \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0430\u0446\u0438\u0438<\/p>\n<\/li>\n<li>\n<p>\u0413\u0438\u0431\u043a\u0430\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432<\/p>\n<\/li>\n<li>\n<p>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432 S3<\/p>\n<\/li>\n<li>\n<p>\u0412\u0430\u043b\u044e\u0442\u043d\u044b\u0435 \u043a\u0443\u0440\u0441\u044b, Continuous Integration, Data Quality<\/p>\n<\/li>\n<\/ul>\n<h3>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 Pivot \u0438 Unpivot \u0434\u043b\u044f \u0442\u0430\u0431\u043b\u0438\u0447\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445<\/h3>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f <em>pivot<\/em> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u0432\u0435\u0440\u043d\u0443\u0442\u044c \u043f\u043b\u043e\u0441\u043a\u0443\u044e \u0434\u0432\u0443\u043c\u0435\u0440\u043d\u0443\u044e \u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0442\u0430\u043a\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c, \u0447\u0442\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0432 \u0441\u0442\u0440\u043e\u043a\u0430\u0445 \u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0442 \u043d\u043e\u0432\u044b\u0435 \u043a\u043e\u043b\u043e\u043d\u043a\u0438. \u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f <em>unpivot<\/em> \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0438 \u0443\u043c\u0435\u043d\u044c\u0448\u0438\u0442\u044c \u0440\u0430\u0437\u043c\u0435\u0440\u043d\u043e\u0441\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0432 \u043a\u043e\u043b\u043e\u043d\u043a\u0438 \u0432 \u0441\u0442\u0440\u043e\u043a\u0438. \u0418\u043d\u0430\u0447\u0435 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u044f\u043c\u0438 \u0441\u043e \u0441\u0432\u043e\u0434\u043d\u044b\u043c\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u043c\u0438 (<em>\u0441ross-tables<\/em>).<\/p>\n<details class=\"spoiler\">\n<summary>\u041f\u0440\u043e\u0449\u0435 \u0432\u0441\u0435\u0433\u043e \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u044d\u0442\u043e \u043d\u0430 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043f\u0440\u0438\u043c\u0435\u0440\u0430\u0445:<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"markdown\">Input: orders  | size | color | |------|-------| | S    | red   | | S    | blue  | | S    | red   | | M    | red   |   Pivot output:  | size | red | blue | |------|-----|------| | S    | 2   | 1    | | M    | 1   | 0    |  --------------  Input: orders  | date       | size | color | status     | |------------|------|-------|------------| | 2017-01-01 | S    | red   | complete   | | 2017-03-01 | S    | red   | processing |   Unpivot output:  | date       | status     | field_name | value | |------------|------------|------------|-------| | 2017-01-01 | complete   | size       | S     | | 2017-01-01 | complete   | color      | red   | | 2017-03-01 | processing | size       | S     | | 2017-03-01 | processing | color      | red   |<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043c\u0430\u043a\u0440\u043e\u0441\u044b dbt, \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0449\u0438\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u0430\u043d\u043d\u044b\u0445 \u0447\u0435\u0440\u0435\u0437 SQL, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043f\u0440\u043e\u0441\u0442\u043e \u0438 \u0433\u0438\u0431\u043a\u043e \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u043e\u0433\u043e \u0444\u043e\u0440\u043c\u0430\u0442\u0430, \u0431\u0435\u0437 \u043f\u0440\u0438\u0432\u044f\u0437\u043a\u0438 \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u043e\u0439 \u0421\u0423\u0411\u0414.<\/p>\n<p>\u0420\u0435\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u044d\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u0442\u044c\u0441\u044f \u2013 \u043f\u043e\u0434\u0433\u043e\u0442\u043e\u0432\u043a\u0430 \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0438 \u043f\u043e \u0437\u0430\u0440\u0430\u043d\u0435\u0435 \u043e\u0433\u043e\u0432\u043e\u0440\u0435\u043d\u043d\u043e\u0439 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0435 \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 \u043a\u043b\u044e\u0447-\u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435.<\/p>\n<p>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<figure class=\"\"><figcaption><\/figcaption><\/figure>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0438\u0440\u0443\u044e\u0449\u0438\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041c\u0430\u043a\u0440\u043e\u0441, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0439 \u0432 SQL-\u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e:<\/p>\n<pre><code class=\"sql\">{{ dbt_utils.unpivot(  \u00a0relation=ref('dim_chauffeurs_labels'),  \u00a0cast_to='varchar',  \u00a0exclude=['actual_dt', 'chauffeur_id'],  \u00a0field_name='label',  \u00a0value_name='value'  ) }}<\/code><\/pre>\n<p>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u0442\u0430\u043a\u043e\u0433\u043e \u043f\u043e\u0434\u0445\u043e\u0434\u0430 \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u044b \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043d\u0435 \u043f\u043e\u044f\u0432\u0438\u043b\u043e\u0441\u044c, \u044d\u0442\u043e \u043d\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043d\u0438 \u0435\u0434\u0438\u043d\u043e\u0433\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434, \u0447\u0442\u043e \u043e\u0447\u0435\u043d\u044c \u0443\u0434\u043e\u0431\u043d\u043e.<\/p>\n<h3>\u0413\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0443\u0440\u0440\u043e\u0433\u0430\u0442\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0438 \u043a\u043b\u044e\u0447\u0430 \u043a\u043e\u043d\u043a\u0430\u0442\u0435\u043d\u0430\u0446\u0438\u0438<\/h3>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u0443\u0440\u0440\u043e\u0433\u0430\u0442\u043d\u044b\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u2013 \u0432\u0430\u0436\u043d\u0435\u0439\u0448\u0438\u0439 \u0430\u0441\u043f\u0435\u043a\u0442 \u043b\u044e\u0431\u043e\u0433\u043e \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0434\u0430\u043d\u043d\u044b\u0445. \u042d\u0442\u043e \u043a\u043b\u044e\u0447\u0438, \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0449\u0438\u0435 \u043e\u0434\u043d\u043e\u0437\u043d\u0430\u0447\u043d\u043e \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0442\u0440\u043e\u043a\u0438 \u0438 \u0441\u043e\u0435\u0434\u0438\u043d\u044f\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0444\u0430\u043a\u0442\u043e\u0432 \u0438 \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u0439. \u041e\u0431\u044b\u0447\u043d\u043e \u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e \u0445\u044d\u0448-\u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043f\u043e\u0434\u0430\u0432\u0430\u044f \u043d\u0430 \u0432\u0445\u043e\u0434 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043a\u043b\u044e\u0447\u0435\u0439 \u0438\u0437 \u0441\u0438\u0441\u0442\u0435\u043c-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432. \u042d\u0442\u0430 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u0430 \u0442\u0430\u043a\u0436\u0435 \u0448\u0438\u0440\u043e\u043a\u043e \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0430 \u0432 Data Vault 2.0 \u0438 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u0441\u043e\u0433\u043b\u0430\u0441\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043c\u0435\u0436\u0434\u0443 \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432.<\/p>\n<p>\u041d\u043e \u0438\u043d\u043e\u0433\u0434\u0430 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u043e\u0433\u043e \u043a\u043b\u044e\u0447\u0430 \u0432\u044b \u0445\u043e\u0442\u0435\u043b\u0438 \u0431\u044b \u0441\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u043d\u0442\u0435\u0440\u043f\u0440\u0435\u0442\u0438\u0440\u0443\u0435\u043c\u043e\u0441\u0442\u044c \u0438 \u0447\u0438\u0442\u0430\u0435\u043c\u043e\u0441\u0442\u044c (<em>human-readable<\/em>) \u0432\u0441\u0435\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439. \u0412 \u0447\u0430\u0441\u0442\u043d\u043e\u0441\u0442\u0438 \u044d\u0442\u043e \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u043e \u0432 \u043c\u0430\u0440\u043a\u0435\u0442\u0438\u043d\u0433\u043e\u0432\u043e\u0439 \u0430\u043d\u0430\u043b\u0438\u0442\u0438\u043a\u0435, \u0433\u0434\u0435 \u043a\u043b\u044e\u0447 \u0441\u0442\u0440\u043e\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043d\u0430\u0431\u043e\u0440 \u043c\u0435\u0442\u043e\u043a: <em>utm_source<\/em>, <em>utm_medium<\/em>, <em>utm_campaign<\/em>, <em>ads_group_id<\/em>, <em>keyword_id<\/em>.\u00a0<\/p>\n<p>\u0423\u0434\u043e\u0431\u043e\u0447\u0438\u0442\u0430\u0435\u043c\u044b\u0435 (<em>human-readable<\/em>) \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f \u043f\u043e\u043c\u043e\u0433\u0430\u044e\u0442 \u0431\u044b\u0441\u0442\u0440\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0438 \u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u044f\u0442\u044c \u0431\u0430\u0433\u0438, \u0432 \u0442\u043e \u0432\u0440\u0435\u043c\u044f \u043a\u0430\u043a \u0445\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0441\u0443\u0440\u0440\u043e\u0433\u0430\u0442\u043d\u044b\u0435 \u043a\u043b\u044e\u0447\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0445 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0439 \u0442\u0430\u0431\u043b\u0438\u0446:<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u044d\u0442\u0438\u0445 \u043a\u043b\u044e\u0447\u0435\u0439 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 <a href=\"https:\/\/github.com\/kzzzr\/mybi-dbt-core\/blob\/master\/macros\/surrogate_key.sql\"><u>hash(), concat(), surrogate_key()<\/u><\/a> (\u0430\u0434\u0430\u043f\u0442\u0435\u0440 MS SQL):<\/p>\n<details class=\"spoiler\">\n<summary>hash(), concat(), surrogate_key() macros<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"sql\">------------------------  --- MSSQL hash macro ---  ------------------------  {% macro hash(field) -%}  \u00a0\u00a0\u00a0HASHBYTES('SHA2_256', {{field}})  {%- endmacro %}  \u00a0  --------------------------  --- MSSQL concat macro ---  --------------------------  {% macro concat(fields) -%}  \u00a0\u00a0\u00a0concat({{ fields|join(', ') }})  {%- endmacro %}  \u00a0  \u00a0  --------------------------  --- Surrogate hash key ---  --------------------------  {%- macro surrogate_key(field_list) -%}  \u00a0  \u00a0\u00a0\u00a0{%- if varargs|length >= 1 %}  \u00a0  \u00a0\u00a0\u00a0{%- do exceptions.warn(\"Warning: the `surrogate_key` macro now takes a single list argument instead of multiple string arguments. Support for multiple string arguments will be deprecated in a future release of dbt-utils.\") -%}  \u00a0  \u00a0\u00a0\u00a0{# first argument is not included in varargs, so add first element to field_list_xf #}  \u00a0\u00a0\u00a0{%- set field_list_xf = [field_list] -%}  \u00a0  \u00a0\u00a0\u00a0{%- for field in varargs %}  \u00a0\u00a0\u00a0{%- set _ = field_list_xf.append(field) -%}  \u00a0\u00a0\u00a0{%- endfor -%}  \u00a0  \u00a0\u00a0\u00a0{%- else -%}  \u00a0  \u00a0\u00a0\u00a0{# if using list, just set field_list_xf as field_list #}  \u00a0\u00a0\u00a0{%- set field_list_xf = field_list -%}  \u00a0  \u00a0\u00a0\u00a0{%- endif -%}  \u00a0  \u00a0  \u00a0\u00a0\u00a0{%- set fields = [] -%}  \u00a0  \u00a0\u00a0\u00a0{%- for field in field_list_xf -%}  \u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- set _ = fields.append(  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\"coalesce(cast(\" ~ field ~ \" as NVARCHAR \" ~ \"), '')\"  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0) -%}  \u00a0  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- if not loop.last %}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- set _ = fields.append(\"'-'\") -%}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{%- endif -%}  \u00a0  \u00a0\u00a0\u00a0{%- endfor -%}  \u00a0  \u00a0\u00a0\u00a0{# {{ concat(fields) }} #}  \u00a0\u00a0\u00a0{{ mybi_dbt_core.hash(mybi_dbt_core.concat(fields)) }}  \u00a0  {%- endmacro -%}<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0421\u043b\u0435\u0434\u0443\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u0438\u0442\u044c \u043e\u0441\u043e\u0431\u043e\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043c\u043e\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p>\u041f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u0430\u0432\u043d\u044b\u0445 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u0432 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u0443\u044e \u0444\u043e\u0440\u043c\u0443<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0439 <em>null,<\/em> \u0435\u0441\u043b\u0438 \u0442\u0430\u043a\u043e\u0432\u044b\u0435 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u044e\u0442<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u043e\u0432 \u043a\u043b\u044e\u0447\u0430<\/p>\n<\/li>\n<li>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044f \u043c\u0435\u0436\u0434\u0443 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 \u043a\u043b\u044e\u0447\u0430 (\u0442\u0438\u0440\u0435, \u043f\u043e\u0434\u0447\u0435\u0440\u043a\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u043b\u044e\u0431\u043e\u0433\u043e \u0434\u0440\u0443\u0433\u043e\u0433\u043e)<\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u044b\u0437\u043e\u0432 \u043c\u0430\u043a\u0440\u043e\u0441\u043e\u0432 \u0432 \u043a\u043e\u0434\u0435 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<pre><code class=\"sql\">select    {{ surrogate_key([\"dt\", \"campaign_id\", \"ads_id\"]) }} as hash_key   , {{ concat_key([\"dt\", \"campaign_id\", \"ads_id\"]) }} as concat_key<\/code><\/pre>\n<p>\u0410\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0439 \u043a\u043e\u0434, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u0442 \u0437\u0430\u043f\u0443\u0449\u0435\u043d \u0432 \u0421\u0423\u0411\u0414 (\u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u0432\u0435\u0440\u0441\u0438\u044f):<\/p>\n<pre><code class=\"sql\">select    HASHBYTES('SHA2_256', concat(coalesce(cast([dt] as NVARCHAR ), ''), '-', coalesce(cast([campaign_id] as NVARCHAR ), ''), '-', coalesce(cast([ads_id] as NVARCHAR ), ''))) as hash_key , concat(coalesce(cast([dt] as NVARCHAR ), ''), '-', coalesce(cast([campaign_id] as NVARCHAR ), ''), '-', coalesce(cast([ads_id] as NVARCHAR ), '')) as concat_key<\/code><\/pre>\n<h3>\u0413\u0438\u0431\u043a\u0430\u044f \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u0446\u0438\u044f \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0438\u0437 \u0442\u0430\u0431\u043b\u0438\u0446-\u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432<\/h3>\n<p>\u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0435 \u0414\u0430\u043d\u043d\u044b\u0445 \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u044f\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u0438\u0437 \u0434\u0435\u0441\u044f\u0442\u043a\u043e\u0432 \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u0441\u043e\u0442\u0435\u043d \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u043e\u0432. \u041a\u0430\u0436\u0434\u044b\u0439 \u0438\u0437 \u043d\u0438\u0445 \u043e\u0431\u043b\u0430\u0434\u0430\u0435\u0442 \u0441\u0432\u043e\u0438\u043c\u0438 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044f\u043c\u0438 \u0438 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0438\u043c\u0435\u0435\u0442 \u0441\u043c\u044b\u0441\u043b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c \u0432\u044b\u0431\u043e\u0440\u043a\u0438, \u043e\u0431\u0440\u0430\u0449\u0430\u044f\u0441\u044c \u043a \u0438\u0441\u0445\u043e\u0434\u043d\u044b\u043c \u0434\u0430\u043d\u043d\u044b\u043c.<\/p>\n<p>\u0418\u043c\u0435\u0439\u0442\u0435 \u0432 \u0432\u0438\u0434\u0443 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0438:<\/p>\n<ul>\n<li>\n<p>\u0427\u0442\u0435\u043d\u0438\u0435 \u0430\u043a\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 (<em>deleted_flag is not true<\/em>)<\/p>\n<\/li>\n<li>\n<p>\u0424\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u043e\u0439 \u0432\u044b\u0431\u043e\u0440\u043a\u0438 \u0434\u043b\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0438 Continuous Integration<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u0438\u0441\u043a \u0434\u0435\u043b\u044c\u0442\u044b \u0434\u043b\u044f \u0438\u043d\u043a\u0440\u0435\u043c\u0435\u043d\u0442\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0432\u0438\u0442\u0440\u0438\u043d<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u0440\u0438 \u044d\u0442\u043e\u043c \u043f\u043e\u043c\u043d\u0438\u0442\u0435, \u0447\u0442\u043e \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u044f \u043a\u043e\u043b\u043e\u043d\u043e\u043a, \u043f\u043e \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u043c \u0434\u0430\u043d\u043d\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u043e\u0442 \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0430 \u043a \u0438\u0441\u0442\u043e\u0447\u043d\u0438\u043a\u0443. \u0420\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c\u0441\u044f \u043c\u043e\u0433\u0443\u0442 \u0442\u0430\u043a\u0436\u0435 \u0438 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u2013 <em>epoch<\/em> (bigint) vs <em>timestamp<\/em>.<\/p>\n<p>\u0412\u0441\u0435 \u044d\u0442\u0438 \u0432\u0432\u043e\u0434\u043d\u044b\u0435 \u0445\u043e\u0440\u043e\u0448\u043e \u043b\u043e\u0436\u0430\u0442\u0441\u044f \u043d\u0430 \u0448\u0430\u0431\u043b\u043e\u043d\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0435 \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 \u043a\u043e\u043d\u0441\u0442\u0440\u0443\u043a\u0446\u0438\u0438 <em>WHERE<\/em>.<\/p>\n<pre><code class=\"sql\">select  \u00a0\u00a0\u00a0...  from {{ source('backend', 'orders') }}  {{ hevo_filter_rows( \u00a0\u00a0\u00a0deleted_rows_filter=true, \u00a0\u00a0\u00a0last_n_days_of_data=false, \u00a0\u00a0\u00a0timestamp_column='created_at', \u00a0\u00a0\u00a0incremental_column='__metadata_timestamp'\u00a0\u00a0\u00a0 ) }}<\/code><\/pre>\n<p>\u0421\u0430\u043c \u043c\u0430\u043a\u0440\u043e\u0441 \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c (\u0441 \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f\u043c\u0438):<\/p>\n<details class=\"spoiler\">\n<summary>macro hevo_filter_rows()<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"sql\">-- filter data for deleted rows; resize for dev, ci pipelines; apply incremental load filters  {% macro hevo_filter_rows(  \u00a0\u00a0\u00a0deleted_rows_filter=true,  \u00a0\u00a0\u00a0last_n_days_of_data=false,  \u00a0\u00a0\u00a0timestamp_column='created_at',  \u00a0\u00a0\u00a0incremental_column='__metadata_timestamp'  ) -%}  \u00a0\u00a0  \u00a0\u00a0\u00a0{#- prepare expression to filter deleted rows by flag __hevo__marked_deleted where it exists\u00a0 -#}  \u00a0\u00a0\u00a0{%- set deleted_rows_expression = '__hevo__marked_deleted is not true' if deleted_rows_filter == true else '1 = 1' -%}  \u00a0  \u00a0\u00a0\u00a0{#- cast epoch to timestamp if necessary -#}  \u00a0\u00a0\u00a0{%- set timestamp_column = epoch_to_timestamp('__hevo__ingested_at')  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if timestamp_column == '__hevo__ingested_at' else timestamp_column -%}  \u00a0  \u00a0\u00a0\u00a0{#- prepare expression to filter rows to last 'development_days_of_data' (e.g. last 3 days) -#}\u00a0\u00a0  \u00a0\u00a0\u00a0{% set get_dev_watermark_query = 'select dateadd(day, ' ~ -1 * var('development_days_of_data') ~ ', current_timestamp::date)' %}  \u00a0\u00a0\u00a0{# {{ log(\"get_dev_watermark_query: \" ~ get_dev_watermark_query, info=True) }} #}  \u00a0\u00a0\u00a0{% if execute %}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0{% set dev_watermark = \"'\" ~ run_query(get_dev_watermark_query).columns[0][0] ~ \"'\" %}  \u00a0\u00a0\u00a0{% endif %}\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0  \u00a0\u00a0\u00a0{%- set dev_rows_expression = timestamp_column ~ ' >= ' ~ dev_watermark  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if target.name in ['dev', 'ci'] and last_n_days_of_data == true else '1 = 1' -%}  \u00a0  \u00a0\u00a0\u00a0{#- prepare expression to filter only delta rows on incremental build -#}  \u00a0\u00a0\u00a0{%- set incremental_expression =  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0epoch_to_timestamp('__hevo__ingested_at') ~ '  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0>= dateadd(h, -24, (select max(' ~ incremental_column ~ ') from ' ~ this ~ '))'  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0if is_incremental() else '1 = 1' -%}  \u00a0  \u00a0\u00a0\u00a0{#- prepare final filter expression -#}  \u00a0\u00a0\u00a0where 1 = 1  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0and {{ deleted_rows_expression }}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0and {{ dev_rows_expression }}  \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0and {{ incremental_expression }}  \u00a0  {%- endmacro -%}<\/code><\/pre>\n<\/p>\n<\/div>\n<\/details>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0434\u043b\u044f \u043f\u0435\u0440\u0432\u043e\u0433\u043e (\u0441 \u043d\u0443\u043b\u044f) \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0432 dev-\u043a\u043e\u043d\u0442\u0443\u0440\u0435:<\/p>\n<pre><code class=\"sql\">select\u00a0  \u00a0\u00a0\u00a0...  from {{ source('backend', 'orders') }}  where 1 = 1 \u00a0\u00a0\u00a0and __hevo__marked_deleted is not true \u00a0\u00a0\u00a0and created_at >= '2021-08-10 00:00:00' \u00a0\u00a0\u00a0and 1 = 1<\/code><\/pre>\n<p>\u00a0<\/p>\n<h3>\u0410\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437 \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430 \u0432 S3<\/h3>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0432\u0441\u043f\u043e\u043c\u043d\u0438\u043c \u043f\u0435\u0440\u0432\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440, \u0433\u0434\u0435 \u043c\u044b \u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u043b\u0438 unpivot-\u0442\u0430\u0431\u043b\u0438\u0446\u0443 \u0434\u043b\u044f \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0435\u0439. \u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0432 \u044d\u0442\u043e\u0442 \u0440\u0430\u0437 \u043e\u043d\u0438 \u043e\u0431\u0440\u0430\u0442\u0438\u043b\u0438\u0441\u044c \u043a \u043d\u0430\u043c \u0441 \u043f\u0440\u043e\u0441\u044c\u0431\u043e\u0439 \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432\u044b\u0433\u0440\u0443\u0437\u043a\u0443 \u043d\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0425\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, \u043d\u043e \u043a\u0430\u043a \u043f\u043b\u043e\u0441\u043a\u0438\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 Object Storage (S3).<\/p>\n<p>\u0412\u043f\u043e\u043b\u043d\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0439 \u0441\u0446\u0435\u043d\u0430\u0440\u0438\u0439. \u041c\u044b \u043c\u043e\u0433\u043b\u0438 \u0431\u044b \u043d\u0430\u0447\u0430\u0442\u044c \u0434\u0443\u043c\u0430\u0442\u044c \u043e\u0431 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u0430\u0445, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c, \u0432\u044b\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u044b, \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u044f\u0437\u044b\u043a\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043d\u043e <em>\u043d\u0435 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0435 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0438 \u0431\u0435\u0437 \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043d\u0430 \u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438<\/em>. \u0412\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u0441\u044f \u0442\u0435\u043c, \u0447\u0442\u043e \u0443\u043c\u0435\u0435\u0442 \u0441\u0430\u043c\u0430 \u0421\u0423\u0411\u0414.<\/p>\n<p>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u044f UNLOAD (\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 Amazon Redshift), \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u043c\u0430\u044f \u043a\u0430\u043a <em>post-hook <\/em>\u043c\u043e\u0434\u0435\u043b\u0438 dbt:<\/p>\n<details class=\"spoiler\">\n<summary>UNLOAD to S3<\/summary>\n<div class=\"spoiler__content\">\n<pre><code class=\"sql\">{{ \u00a0\u00a0\u00a0config( \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0materialized='view',<\/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-385726","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/385726","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=385726"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/385726\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=385726"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=385726"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=385726"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}