HomeWork20250228.sql 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331
  1. do $$
  2. begin
  3. /*
  4. Скрипт создания информационной базы данных
  5. Согласно технического задания https://git.hostfl.ru/VolovikovAlex/Study2025
  6. Редакция 2025-02-28
  7. Edit by valex
  8. */
  9. /*
  10. 1. Удаляем старые элементы
  11. ======================================
  12. */
  13. drop view if exists vw_report_fails_statistics;
  14. drop view if exists vw_report_fails_height_statistics;
  15. raise notice 'Запускаем создание новой структуры базы данных meteo';
  16. begin
  17. -- Связи
  18. alter table if exists public.measurment_input_params
  19. drop constraint if exists measurment_type_id_fk;
  20. alter table if exists public.employees
  21. drop constraint if exists military_rank_id_fk;
  22. alter table if exists public.measurment_baths
  23. drop constraint if exists measurment_input_param_id_fk;
  24. alter table if exists public.measurment_baths
  25. drop constraint if exists emploee_id_fk;
  26. alter table if exists public.calc_height_correction
  27. drop constraint if exists measurment_type_id_fk;
  28. alter table if exists public.calc_temperature_height_correction
  29. drop constraint if exists calc_temperature_header_id_fk;
  30. alter table if exists public.calc_temperature_height_correction
  31. drop constraint if exists calc_height_id_fk;
  32. alter table if exists public.calc_header_correction
  33. drop constraint if exists measurment_type_id_fk;
  34. alter table if exists public.calc_wind_speed_height_correction
  35. drop constraint if exists calc_wind_speed_height_correction_calc_height_id_fk;
  36. -- Таблицы
  37. drop table if exists public.measurment_input_params;
  38. drop table if exists public.measurment_baths;
  39. drop table if exists public.employees;
  40. drop table if exists public.measurment_types;
  41. drop table if exists public.military_ranks;
  42. drop table if exists public.measurment_settings;
  43. drop table if exists public.calc_height_correction;
  44. drop table if exists public.calc_temperature_correction;
  45. drop table if exists public.calc_temperature_height_correction;
  46. drop table if exists public.calc_header_correction;
  47. drop table if exists public.calc_wind_speed_height_correction;
  48. -- Нумераторы
  49. drop sequence if exists public.measurment_input_params_seq cascade;
  50. drop sequence if exists public.measurment_baths_seq cascade;
  51. drop sequence if exists public.employees_seq cascade;
  52. drop sequence if exists public.military_ranks_seq cascade;
  53. drop sequence if exists public.measurment_types_seq cascade;
  54. drop sequence if exists public.calc_height_correction_seq cascade;
  55. drop sequence if exists public.calc_temperature_height_correction_seq cascade;
  56. drop sequence if exists public.calc_header_correction_seq cascade;
  57. drop sequence if exists public.calc_wind_speed_height_correction_seq cascade;
  58. end;
  59. raise notice 'Удаление старых данных выполнено успешно';
  60. /*
  61. 2. Добавляем структуры данных
  62. ================================================
  63. */
  64. -- Справочник должностей
  65. create table military_ranks
  66. (
  67. id integer primary key not null,
  68. description character varying(255)
  69. );
  70. insert into military_ranks(id, description)
  71. values(1,'Рядовой'),(2,'Лейтенант');
  72. create sequence military_ranks_seq start 3;
  73. alter table military_ranks alter column id set default nextval('public.military_ranks_seq');
  74. -- Пользователя
  75. create table employees
  76. (
  77. id integer primary key not null,
  78. name text,
  79. birthday timestamp ,
  80. military_rank_id integer not null
  81. );
  82. insert into employees(id, name, birthday,military_rank_id )
  83. values(1, 'Воловиков Александр Сергеевич','1978-06-24', 2);
  84. create sequence employees_seq start 2;
  85. alter table employees alter column id set default nextval('public.employees_seq');
  86. -- Устройства для измерения
  87. create table measurment_types
  88. (
  89. id integer primary key not null,
  90. short_name character varying(50),
  91. description text
  92. );
  93. insert into measurment_types(id, short_name, description)
  94. values(1, 'ДМК', 'Десантный метео комплекс'),
  95. (2,'ВР','Ветровое ружье');
  96. create sequence measurment_types_seq start 3;
  97. alter table measurment_types alter column id set default nextval('public.measurment_types_seq');
  98. -- Таблица с параметрами
  99. create table measurment_input_params
  100. (
  101. id integer primary key not null,
  102. measurment_type_id integer not null,
  103. height numeric(8,2) default 0,
  104. temperature numeric(8,2) default 0,
  105. pressure numeric(8,2) default 0,
  106. wind_direction numeric(8,2) default 0,
  107. wind_speed numeric(8,2) default 0,
  108. bullet_demolition_range numeric(8,2) default 0
  109. );
  110. insert into measurment_input_params(id, measurment_type_id, height, temperature, pressure, wind_direction,wind_speed )
  111. values(1, 1, 100,12,34,0.2,45);
  112. create sequence measurment_input_params_seq start 2;
  113. alter table measurment_input_params alter column id set default nextval('public.measurment_input_params_seq');
  114. -- Таблица с историей
  115. create table measurment_baths
  116. (
  117. id integer primary key not null,
  118. emploee_id integer not null,
  119. measurment_input_param_id integer not null,
  120. started timestamp default now()
  121. );
  122. insert into measurment_baths(id, emploee_id, measurment_input_param_id)
  123. values(1, 1, 1);
  124. create sequence measurment_baths_seq start 2;
  125. alter table measurment_baths alter column id set default nextval('public.measurment_baths_seq');
  126. -- Таблица с настройками
  127. create table measurment_settings
  128. (
  129. key character varying(100) primary key not null,
  130. value character varying(255) ,
  131. description text
  132. );
  133. insert into measurment_settings(key, value, description)
  134. values('min_temperature', '-10', 'Минимальное значение температуры'),
  135. ('max_temperature', '50', 'Максимальное значение температуры'),
  136. ('min_pressure','500','Минимальное значение давления'),
  137. ('max_pressure','900','Максимальное значение давления'),
  138. ('min_wind_direction','0','Минимальное значение направления ветра'),
  139. ('max_wind_direction','59','Максимальное значение направления ветра'),
  140. ('calc_table_temperature','15.9','Табличное значение температуры'),
  141. ('calc_table_pressure','750','Табличное значение наземного давления'),
  142. ('min_height','0','Минимальная высота'),
  143. ('max_height','400','Максимальная высота');
  144. raise notice 'Создание общих справочников и наполнение выполнено успешно';
  145. /*
  146. 3. Подготовка расчетных структур
  147. ==========================================
  148. */
  149. create table calc_temperature_correction
  150. (
  151. temperature numeric(8,2) not null primary key,
  152. correction numeric(8,2) not null
  153. );
  154. insert into public.calc_temperature_correction(temperature, correction)
  155. Values(0, 0.5),(5, 0.5),(10, 1), (20,1), (25, 2), (30, 3.5), (40, 4.5);
  156. drop type if exists interpolation_type;
  157. create type interpolation_type as
  158. (
  159. x0 numeric(8,2),
  160. x1 numeric(8,2),
  161. y0 numeric(8,2),
  162. y1 numeric(8,2)
  163. );
  164. -- Тип для входных параметров
  165. drop type if exists input_params cascade;
  166. create type input_params as
  167. (
  168. height numeric(8,2),
  169. temperature numeric(8,2),
  170. pressure numeric(8,2),
  171. wind_direction numeric(8,2),
  172. wind_speed numeric(8,2),
  173. bullet_demolition_range numeric(8,2)
  174. );
  175. -- Тип с результатами проверки
  176. drop type if exists check_result cascade;
  177. create type check_result as
  178. (
  179. is_check boolean,
  180. error_message text,
  181. params input_params
  182. );
  183. -- Результат расчета коррекций для температуры по высоте
  184. drop type if exists temperature_correction cascade;
  185. create type temperature_correction as
  186. (
  187. calc_height_id integer,
  188. height integer,
  189. -- Приращение по температуре
  190. temperature_deviation integer
  191. );
  192. -- Результат расчета скорости среднего ветра и приращение среднего ветра
  193. drop type if exists wind_direction_correction cascade;
  194. create type wind_direction_correction as
  195. (
  196. calc_height_id integer,
  197. height integer,
  198. -- Приращение по скорости ветра
  199. wind_speed_deviation integer,
  200. -- Приращение среднего ветра
  201. wind_deviation integer
  202. );
  203. -- Таблица заголовков к поправочных таблицам
  204. create sequence calc_header_correction_seq;
  205. create table calc_header_correction
  206. (
  207. id integer not null primary key default nextval('public.calc_header_correction_seq'),
  208. measurment_type_id integer not null,
  209. header varchar(100) not null,
  210. description text not null,
  211. values integer[] not null
  212. );
  213. -- Добавим уникальный индекс для отсечки ошибок
  214. create unique index ix_calc_header_correction_header_type on calc_header_correction(measurment_type_id, header);
  215. -- Добавим заголовки
  216. insert into calc_header_correction(measurment_type_id, header, description, values)
  217. values (1, 'table2', 'Заголовок для Таблицы № 2 (ДМК)', array[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50]),
  218. (2, 'table2','Заголовок для Таблицы № 2 (ВР)', array[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 40, 50]),
  219. (2, 'table3', 'Заголовок для Таблицы № 3 (ВР)', array[40,50,60,70,80,90,100,110,120,130,140,150]);
  220. -- Таблица 2 список высот в разрезе типа оборудования
  221. create sequence calc_height_correction_seq;
  222. create table calc_height_correction
  223. (
  224. id integer primary key not null default nextval('public.calc_height_correction_seq'),
  225. height integer not null,
  226. measurment_type_id integer not null
  227. );
  228. insert into calc_height_correction(height, measurment_type_id)
  229. values(200,1),(400,1),(800,1),(1200,1),(1600,1),(2000,1),(2400,1),(3000,1),(4000,1),
  230. (200,2),(400,2),(800,2),(1200,2),(1600,2),(2000,2),(2400,2),(3000,2),(4000,2);
  231. -- Таблица 2 набор корректировок
  232. create sequence calc_temperature_height_correction_seq;
  233. create table calc_temperature_height_correction
  234. (
  235. id integer primary key not null default nextval('public.calc_temperature_height_correction_seq'),
  236. calc_height_id integer not null,
  237. calc_temperature_header_id integer not null,
  238. positive_values numeric[],
  239. negative_values numeric[]
  240. );
  241. -- Данные для ветрового ружья
  242. insert into calc_temperature_height_correction(calc_height_id, calc_temperature_header_id, positive_values, negative_values)
  243. values
  244. (10,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[ -1, -2, -3, -4, -5, -6, -7, -8, -8, -9, -20, -29, -39, -49]), --200
  245. (11,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -4, -5, -6, -6, -7, -8, -9, -19, -29, -38, -48]), --400
  246. (12,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -4, -5, -6, -6, -7, -7, -8, -18, -28, -37, -46]), --800
  247. (13,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -4, -4, -5, -5, -6, -7, -8, -17, -26, -35, -44]), --1200
  248. (14,1,array[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -3, -4, -4, -5, -6, -7, -7, -17, -25, -34, -42]), --1600
  249. (15,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -3, -4, -4, -5, -6, -6, -7, -16, -24, -32, -40]), --2000
  250. (16,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -2, -3, -4, -4, -5, -5, -6, -7, -15, -23, -31, -38]), --2400
  251. (17,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -2, -3, -4, -4, -4, -5, -5, -6, -15, -22, -30, -37]), --3000
  252. (18,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[ -1, -2, -2, -3, -4, -4, -4, -4, -5, -6, -14, -20, -27, -34]); --4000
  253. -- Данные для ДМК
  254. insert into calc_temperature_height_correction(calc_height_id, calc_temperature_header_id, positive_values, negative_values)
  255. values
  256. (1,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[ -1, -2, -3, -4, -5, -6, -7, -8, -8, -9, -20, -29, -39, -49]), --200
  257. (2,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -4, -5, -6, -6, -7, -8, -9, -19, -29, -38, -48]), --400
  258. (3,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -4, -5, -6, -6, -7, -7, -8, -18, -28, -37, -46]), --800
  259. (4,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -4, -4, -5, -5, -6, -7, -8, -17, -26, -35, -44]), --1200
  260. (5,1,array[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -3, -4, -4, -5, -6, -7, -7, -17, -25, -34, -42]), --1600
  261. (6,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -3, -3, -4, -4, -5, -6, -6, -7, -16, -24, -32, -40]), --2000
  262. (7,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -2, -3, -4, -4, -5, -5, -6, -7, -15, -23, -31, -38]), --2400
  263. (8,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[-1, -2, -2, -3, -4, -4, -4, -5, -5, -6, -15, -22, -30, -37]), --3000
  264. (9,1,array[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, 30, 30], array[ -1, -2, -2, -3, -4, -4, -4, -4, -5, -6, -14, -20, -27, -34]); --4000
  265. -- Таблица 3 корректировка сноса пуль
  266. -- Для расчета приращение среднего ветра относительно направления приземного ветра
  267. create sequence calc_wind_speed_height_correction_seq;
  268. drop table if exists calc_wind_speed_height_correction;
  269. create table calc_wind_speed_height_correction
  270. (
  271. id integer not null primary key default nextval('public.calc_wind_speed_height_correction_seq'),
  272. calc_height_id integer not null,
  273. values integer[] not null,
  274. delta integer not null
  275. );
  276. -- Для ветрового ружья
  277. insert into calc_wind_speed_height_correction(calc_height_id, values, delta)
  278. values
  279. (10, array[3, 4, 5, 6, 7, 7, 8, 9, 10, 11, 12, 12], 0), -- 200
  280. (11, array[4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 1),-- 400
  281. (12, array[4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16], 2), -- 800
  282. (13, array[4, 5, 7, 8, 8, 9, 11, 12, 13, 15, 15, 16], 2), -- 1200
  283. (14, array[4, 6, 7, 8, 9, 10, 11, 13, 14, 15, 17, 17], 3), -- 1600
  284. (15, array[4, 6, 7, 8, 9, 10, 11, 13, 14, 16, 17, 18], 3), -- 2000
  285. (16, array[4, 6, 8, 9, 9, 10, 12, 14, 15, 16, 18, 19], 3), -- 2400
  286. (17, array[5, 6, 8, 9, 10, 11, 12, 14, 15, 17, 18, 19], 4), -- 3000
  287. (18, array[5, 6, 8, 9, 10, 11, 12, 14, 16, 18, 19, 20],4) -- 4000
  288. ;
  289. raise notice 'Расчетные структуры сформированы';
  290. /*
  291. 4. Создание связей
  292. ==========================================
  293. */
  294. begin
  295. -- Связь между заголовком корректирующих таблиц и типом оборудования (один ко многим)
  296. alter table public.calc_header_correction
  297. add constraint measurment_type_id_fk
  298. foreign key (measurment_type_id)
  299. references public.measurment_types(id);
  300. -- Связь между списком высот и типом оборудования (один ко многим)
  301. alter table public.calc_height_correction
  302. add constraint measurment_type_id_fk
  303. foreign key (measurment_type_id)
  304. references public.measurment_types(id);
  305. -- Связи между таблицей с корректировками и заголовками (один ко многим)
  306. alter table public.calc_temperature_height_correction
  307. add constraint calc_temperature_header_id_fk
  308. foreign key (calc_temperature_header_id)
  309. references public.calc_temperature_height_correction(id);
  310. alter table public.calc_temperature_height_correction
  311. add constraint calc_height_id_fk
  312. foreign key (calc_height_id)
  313. references public.calc_height_correction(id);
  314. -- Связь между пачками измерений с пользователями (один ко многим)
  315. alter table public.measurment_baths
  316. add constraint emploee_id_fk
  317. foreign key (emploee_id)
  318. references public.employees (id);
  319. -- Связь между пачками измерений и измерениями (один к одному)
  320. alter table public.measurment_baths
  321. add constraint measurment_input_param_id_fk
  322. foreign key(measurment_input_param_id)
  323. references public.measurment_input_params(id);
  324. -- Связь между измерениями и типом оборудования (один ко многим)
  325. alter table public.measurment_input_params
  326. add constraint measurment_type_id_fk
  327. foreign key(measurment_type_id)
  328. references public.measurment_types (id);
  329. -- Связь между пользователем и званием (один ко многим)
  330. alter table public.employees
  331. add constraint military_rank_id_fk
  332. foreign key(military_rank_id)
  333. references public.military_ranks (id);
  334. -- Связь между высотами и таблицей корректировки сноса пуль
  335. alter table public.calc_wind_speed_height_correction
  336. add constraint calc_wind_speed_height_correction_calc_height_id_fk
  337. foreign key(calc_height_id)
  338. references public.calc_height_correction (id);
  339. end;
  340. raise notice 'Связи сформированы';
  341. raise notice 'Формируем индексы';
  342. create index if not exists ix_measurment_baths_emploee_id on public.measurment_baths(emploee_id);
  343. create index if not exists ix_measurment_baths_measurment_input_param_id on public.measurment_baths(measurment_input_param_id);
  344. raise notice 'Индексы сформирован';
  345. /*
  346. 4. Создает расчетные и вспомогательные функции
  347. ==========================================
  348. */
  349. -- Функция для расчета отклонения приземной виртуальной температуры
  350. drop function if exists public.fn_calc_header_temperature;
  351. create function public.fn_calc_header_temperature(
  352. par_temperature numeric(8,2))
  353. returns numeric(8,2)
  354. language 'plpgsql'
  355. as $BODY$
  356. declare
  357. default_temperature numeric(8,2) default 15.9;
  358. default_temperature_key character varying default 'calc_table_temperature' ;
  359. virtual_temperature numeric(8,2) default 0;
  360. deltaTv numeric(8,2) default 0;
  361. var_result numeric(8,2) default 0;
  362. begin
  363. raise notice 'Расчет отклонения приземной виртуальной температуры по температуре %', par_temperature;
  364. -- Определим табличное значение температуры
  365. Select coalesce(value::numeric(8,2), default_temperature)
  366. from public.measurment_settings
  367. into virtual_temperature
  368. where
  369. key = default_temperature_key;
  370. -- Вирутальная поправка
  371. deltaTv := par_temperature +
  372. public.fn_calc_temperature_interpolation(par_temperature => par_temperature);
  373. -- Отклонение приземной виртуальной температуры
  374. var_result := deltaTv - virtual_temperature;
  375. return var_result;
  376. end;
  377. $BODY$;
  378. -- Функция для формирования даты в специальном формате
  379. drop function if exists public.fn_calc_header_period;
  380. create function public.fn_calc_header_period(
  381. par_period timestamp with time zone)
  382. returns text
  383. language 'sql'
  384. return
  385. -- ДД
  386. case when (extract(day from par_period) < 10::numeric) then '0'::text else ''::text end ||
  387. extract(day from par_period)::text ||
  388. -- ЧЧ
  389. case when (extract(hour from par_period) < 10::numeric) then '0'::text else ''::text end ||
  390. extract(hour from par_period)::text ||
  391. -- Десятки минут
  392. case when (extract(minute from par_period) < 10::numeric) then '0'::text
  393. else
  394. left(extract(minute from par_period)::text, 1)
  395. end;
  396. -- Функция для расчета отклонения наземного давления
  397. drop function if exists public.fn_calc_header_pressure;
  398. create function public.fn_calc_header_pressure
  399. (
  400. par_pressure numeric(8,2))
  401. returns numeric(8,2)
  402. language 'plpgsql'
  403. as $body$
  404. declare
  405. default_pressure numeric(8,2) default 750;
  406. table_pressure numeric(8,2) default null;
  407. default_pressure_key character varying default 'calc_table_pressure' ;
  408. begin
  409. raise notice 'Расчет отклонения наземного давления для %', par_pressure;
  410. -- Определяем граничное табличное значение
  411. if not exists (select 1 from public.measurment_settings where key = default_pressure_key ) then
  412. Begin
  413. table_pressure := default_pressure;
  414. end;
  415. else
  416. begin
  417. select value::numeric(18,2)
  418. into table_pressure
  419. from public.measurment_settings where key = default_pressure_key;
  420. end;
  421. end if;
  422. -- Результат
  423. return par_pressure - coalesce(table_pressure,table_pressure) ;
  424. end;
  425. $body$;
  426. -- Функция для проверки входных параметров
  427. drop function if exists public.fn_check_input_params(numeric(8,2), numeric(8,2), numeric(8,2), numeric(8,2), numeric(8,2), numeric(8,2));
  428. create function public.fn_check_input_params(
  429. par_height numeric,
  430. par_temperature numeric,
  431. par_pressure numeric,
  432. par_wind_direction numeric,
  433. par_wind_speed numeric,
  434. par_bullet_demolition_range numeric)
  435. returns check_result
  436. language 'plpgsql'
  437. as $body$
  438. declare
  439. var_result public.check_result;
  440. begin
  441. var_result.is_check = False;
  442. -- Температура
  443. if not exists (
  444. select 1 from (
  445. select
  446. coalesce(min_temperature , '0')::numeric(8,2) as min_temperature,
  447. coalesce(max_temperature, '0')::numeric(8,2) as max_temperature
  448. from
  449. (select 1 ) as t
  450. cross join
  451. ( select value as min_temperature from public.measurment_settings where key = 'min_temperature' ) as t1
  452. cross join
  453. ( select value as max_temperature from public.measurment_settings where key = 'max_temperature' ) as t2
  454. ) as t
  455. where
  456. par_temperature between min_temperature and max_temperature
  457. ) then
  458. var_result.error_message := format('Температура % не укладывает в диаппазон!', par_temperature);
  459. end if;
  460. var_result.params.temperature = par_temperature;
  461. -- Давление
  462. if not exists (
  463. select 1 from (
  464. select
  465. coalesce(min_pressure , '0')::numeric(8,2) as min_pressure,
  466. coalesce(max_pressure, '0')::numeric(8,2) as max_pressure
  467. from
  468. (select 1 ) as t
  469. cross join
  470. ( select value as min_pressure from public.measurment_settings where key = 'min_pressure' ) as t1
  471. cross join
  472. ( select value as max_pressure from public.measurment_settings where key = 'max_pressure' ) as t2
  473. ) as t
  474. where
  475. par_pressure between min_pressure and max_pressure
  476. ) then
  477. var_result.error_message := format('Давление %s не укладывает в диаппазон!', par_pressure);
  478. end if;
  479. var_result.params.pressure = par_pressure;
  480. -- Высота
  481. if not exists (
  482. select 1 from (
  483. select
  484. coalesce(min_height , '0')::numeric(8,2) as min_height,
  485. coalesce(max_height, '0')::numeric(8,2) as max_height
  486. from
  487. (select 1 ) as t
  488. cross join
  489. ( select value as min_height from public.measurment_settings where key = 'min_height' ) as t1
  490. cross join
  491. ( select value as max_height from public.measurment_settings where key = 'max_height' ) as t2
  492. ) as t
  493. where
  494. par_height between min_height and max_height
  495. ) then
  496. var_result.error_message := format('Высота %s не укладывает в диаппазон!', par_height);
  497. end if;
  498. var_result.params.height = par_height;
  499. -- Напрвление ветра
  500. if not exists (
  501. select 1 from (
  502. select
  503. coalesce(min_wind_direction , '0')::numeric(8,2) as min_wind_direction,
  504. coalesce(max_wind_direction, '0')::numeric(8,2) as max_wind_direction
  505. from
  506. (select 1 ) as t
  507. cross join
  508. ( select value as min_wind_direction from public.measurment_settings where key = 'min_wind_direction' ) as t1
  509. cross join
  510. ( select value as max_wind_direction from public.measurment_settings where key = 'max_wind_direction' ) as t2
  511. )
  512. where
  513. par_wind_direction between min_wind_direction and max_wind_direction
  514. ) then
  515. var_result.error_message := format('Направление ветра %s не укладывает в диаппазон!', par_wind_direction);
  516. end if;
  517. var_result.params.wind_direction = par_wind_direction;
  518. var_result.params.wind_speed = par_wind_speed;
  519. if coalesce(var_result.error_message,'') = '' then
  520. var_result.is_check = True;
  521. end if;
  522. return var_result;
  523. end;
  524. $body$;
  525. -- Функция для проверки параметров
  526. drop function if exists public.fn_check_input_params(input_params);
  527. create function public.fn_check_input_params(
  528. par_param input_params
  529. )
  530. returns public.input_params
  531. language 'plpgsql'
  532. as $body$
  533. declare
  534. var_result check_result;
  535. begin
  536. var_result := fn_check_input_params(
  537. par_param.height, par_param.temperature, par_param.pressure, par_param.wind_direction,
  538. par_param.wind_speed, par_param.bullet_demolition_range
  539. );
  540. if var_result.is_check = False then
  541. raise exception 'Ошибка %', var_result.error_message;
  542. end if;
  543. return var_result.params;
  544. end ;
  545. $body$;
  546. -- Функция для расчета интерполяции
  547. drop function if exists public.fn_calc_temperature_interpolation;
  548. create function public.fn_calc_temperature_interpolation(
  549. par_temperature numeric(8,2))
  550. returns numeric
  551. language 'plpgsql'
  552. as $body$
  553. -- Расчет интерполяции
  554. declare
  555. var_interpolation interpolation_type;
  556. var_result numeric(8,2) default 0;
  557. var_min_temparure numeric(8,2) default 0;
  558. var_max_temperature numeric(8,2) default 0;
  559. var_denominator numeric(8,2) default 0;
  560. begin
  561. raise notice 'Расчет интерполяции для температуры %', par_temperature;
  562. -- Проверим, возможно температура совпадает со значением в справочнике
  563. if exists (select 1 from public.calc_temperature_correction where temperature = par_temperature ) then
  564. begin
  565. select correction
  566. into var_result
  567. from public.calc_temperature_correction
  568. where
  569. temperature = par_temperature;
  570. end;
  571. else
  572. begin
  573. -- Получим диапазон в котором работают поправки
  574. select min(temperature), max(temperature)
  575. into var_min_temparure, var_max_temperature
  576. from public.calc_temperature_correction;
  577. if par_temperature < var_min_temparure or
  578. par_temperature > var_max_temperature then
  579. raise exception 'Некорректно передан параметр! Невозможно рассчитать поправку. Значение должно укладываться в диаппазон: %, %',
  580. var_min_temparure, var_max_temperature;
  581. end if;
  582. -- Получим граничные параметры
  583. select x0, y0, x1, y1
  584. into var_interpolation.x0, var_interpolation.y0, var_interpolation.x1, var_interpolation.y1
  585. from
  586. (
  587. select t1.temperature as x0, t1.correction as y0
  588. from public.calc_temperature_correction as t1
  589. where t1.temperature <= par_temperature
  590. order by t1.temperature desc
  591. limit 1
  592. ) as leftPart
  593. cross join
  594. (
  595. select t1.temperature as x1, t1.correction as y1
  596. from public.calc_temperature_correction as t1
  597. where t1.temperature >= par_temperature
  598. order by t1.temperature
  599. limit 1
  600. ) as rightPart;
  601. raise notice 'Граничные значения %', var_interpolation;
  602. -- Расчет поправки
  603. var_denominator := var_interpolation.x1 - var_interpolation.x0;
  604. if var_denominator = 0.0 then
  605. raise exception 'Деление на нуль. Возможно, некорректные данные в таблице с поправками!';
  606. end if;
  607. var_result := (par_temperature - var_interpolation.x0) * (var_interpolation.y1 - var_interpolation.y0) / var_denominator + var_interpolation.y0;
  608. end;
  609. end if;
  610. return var_result;
  611. end;
  612. $body$;
  613. -- Функция для генерации случайной даты
  614. drop function if exists fn_get_random_timestamp;
  615. create function fn_get_random_timestamp(
  616. par_min_value timestamp,
  617. par_max_value timestamp)
  618. returns timestamp
  619. language 'plpgsql'
  620. as $body$
  621. begin
  622. return random() * (par_max_value - par_min_value) + par_min_value;
  623. end;
  624. $body$;
  625. -- Функция для генерации случайного целого числа из диаппазона
  626. drop function if exists fn_get_randon_integer;
  627. create function fn_get_randon_integer(
  628. par_min_value integer,
  629. par_max_value integer
  630. )
  631. returns integer
  632. language 'plpgsql'
  633. as $body$
  634. begin
  635. return floor((par_max_value + 1 - par_min_value)*random())::integer + par_min_value;
  636. end;
  637. $body$;
  638. -- Функция для гнерации случайного текста
  639. drop function if exists fn_get_random_text;
  640. create function fn_get_random_text(
  641. par_length int,
  642. par_list_of_chars text DEFAULT 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмнопрстуфхцчшщъыьэюяABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_0123456789'
  643. )
  644. returns text
  645. language 'plpgsql'
  646. as $body$
  647. declare
  648. var_len_of_list integer default length(par_list_of_chars);
  649. var_position integer;
  650. var_result text = '';
  651. var_random_number integer;
  652. var_max_value integer;
  653. var_min_value integer;
  654. begin
  655. var_min_value := 10;
  656. var_max_value := 50;
  657. for var_position in 1 .. par_length loop
  658. -- добавляем к строке случайный символ
  659. var_random_number := fn_get_randon_integer(var_min_value, var_max_value );
  660. var_result := var_result || substr(par_list_of_chars, var_random_number ,1);
  661. end loop;
  662. return var_result;
  663. end;
  664. $body$;
  665. -- Функция для расчета метео приближенный
  666. drop function if exists fn_calc_header_meteo_avg;
  667. create function fn_calc_header_meteo_avg(
  668. par_params input_params
  669. )
  670. returns text
  671. language 'plpgsql'
  672. as $body$
  673. declare
  674. var_result text;
  675. var_params input_params;
  676. begin
  677. -- Проверяю аргументы
  678. var_params := public.fn_check_input_params(par_params);
  679. select
  680. -- Дата
  681. public.fn_calc_header_period(now()) ||
  682. --Высота расположения метеопоста над уровнем моря.
  683. lpad( 340::text, 4, '0' ) ||
  684. -- Отклонение наземного давления атмосферы
  685. lpad(
  686. case when coalesce(var_params.pressure,0) < 0 then
  687. '5'
  688. else ''
  689. end ||
  690. lpad ( abs(( coalesce(var_params.pressure, 0) )::int)::text,2,'0')
  691. , 3, '0') as "БББ",
  692. -- Отклонение приземной виртуальной температуры
  693. lpad(
  694. case when coalesce( var_params.temperature, 0) < 0 then
  695. '5'
  696. else
  697. ''
  698. end ||
  699. ( coalesce(var_params.temperature,0)::int)::text
  700. , 2,'0')
  701. into var_result;
  702. return var_result;
  703. end;
  704. $body$;
  705. -- Процедура для расчета поправок по температуре в разрезе высот
  706. create procedure public.sp_calc_temperature_deviation(
  707. in par_temperature_correction numeric(8,2),
  708. in par_measurement_type_id integer,
  709. inout par_corrections temperature_correction[]
  710. )
  711. language 'plpgsql'
  712. as $BODY$
  713. declare
  714. var_row record;
  715. var_index integer;
  716. var_header_correction integer[];
  717. var_right_index integer;
  718. var_left_index integer;
  719. var_header_index integer;
  720. var_deviation integer;
  721. var_table integer[];
  722. var_correction temperature_correction;
  723. var_table_row text;
  724. begin
  725. -- Проверяем наличие данные в таблице
  726. if not exists (
  727. select 1
  728. from public.calc_height_correction as t1
  729. inner join public.calc_temperature_height_correction as t2
  730. on t2.calc_height_id = t1.id
  731. where
  732. measurment_type_id = par_measurement_type_id
  733. ) then
  734. raise exception 'Для расчета поправок к температуре не хватает данных!';
  735. end if;
  736. raise notice '| Высота | Поправка |';
  737. raise notice '|----------|-----------|';
  738. for var_row in
  739. -- Запрос на выборку высот
  740. select t2.*, t1.height
  741. from public.calc_height_correction as t1
  742. inner join public.calc_temperature_height_correction as t2
  743. on t2.calc_height_id = t1.id
  744. where measurment_type_id = par_measurement_type_id
  745. loop
  746. -- Получаем индекс корректировки
  747. var_index := par_temperature_correction::integer;
  748. -- Получаем заголовок
  749. var_header_correction := (select values from public.calc_header_correction
  750. where id = var_row.calc_temperature_header_id and header = 'table2');
  751. -- Проверяем данные
  752. if array_length(var_header_correction, 1) = 0 then
  753. raise exception 'Невозможно произвести расчет по высоте % Некорректные исходные данные или настройки', var_row.height;
  754. end if;
  755. if array_length(var_header_correction, 1) < var_index then
  756. raise exception 'Невозможно произвести расчет по высоте % Некорректные исходные данные или настройки', var_row.height;
  757. end if;
  758. -- Получаем левый и правый индекс
  759. var_right_index := abs(var_index % 10);
  760. var_header_index := abs(var_index) - var_right_index;
  761. -- Определяем корретировки
  762. if par_temperature_correction >= 0 then
  763. var_table := var_row.positive_values;
  764. else
  765. var_table := var_row.negative_values;
  766. end if;
  767. if var_header_index = 0 then
  768. var_header_index := 1;
  769. end if;
  770. var_left_index := var_header_correction[ var_header_index];
  771. if var_left_index = 0 then
  772. var_left_index := 1;
  773. end if;
  774. -- Поправка на высоту
  775. var_deviation:= var_table[ var_left_index ] + var_table[ var_right_index ];
  776. select '|' || lpad(var_row.height::text,10, ' ') || '|' || lpad(var_deviation::text,11,' ') || '|'
  777. into
  778. var_table_row;
  779. raise notice '%', var_table_row;
  780. var_correction.calc_height_id := var_row.calc_height_id;
  781. var_correction.height := var_row.height;
  782. var_correction.temperature_deviation := var_deviation;
  783. par_corrections := array_append(par_corrections, var_correction);
  784. end loop;
  785. raise notice '|----------|-----------|';
  786. end;
  787. $BODY$;
  788. -- Процедура для расчета скорости среднего ветра и направления среднего ветра
  789. create or replace procedure public.sp_calc_wind_speed_deviation(
  790. IN par_bullet_demolition_range numeric,
  791. IN par_measurement_type_id integer,
  792. INOUT par_corrections wind_direction_correction[])
  793. language 'plpgsql'
  794. as $body$
  795. declare
  796. var_row record;
  797. var_index integer;
  798. var_correction wind_direction_correction;
  799. var_header_correction integer[];
  800. var_header_index integer;
  801. var_table integer[];
  802. var_deviation integer;
  803. var_table_row text;
  804. begin
  805. if coalesce(par_bullet_demolition_range, -1) < 0 then
  806. raise exception 'Некорректно переданы параметры! Значение par_bullet_demolition_range %', par_bullet_demolition_range;
  807. end if;
  808. if not exists ( select 1 from public.calc_height_correction
  809. where measurment_type_id = par_measurement_type_id) then
  810. raise exception 'Для устройства с кодом % не найдены значения высот в таблице calc_height_correction!', par_measurement_type_id;
  811. end if;
  812. -- Получаем индекс корректировки
  813. var_index := (par_bullet_demolition_range / 10)::integer - 4;
  814. if var_index < 0 then
  815. var_index := 1;
  816. end if;
  817. -- Получаем заголовок
  818. var_header_correction := (select values from public.calc_header_correction
  819. where
  820. header = 'table3'
  821. and measurment_type_id = par_measurement_type_id );
  822. -- Проверяем данные
  823. if array_length(var_header_correction, 1) = 0 then
  824. raise exception 'Невозможно произвести расчет по высоте. Некорректные исходные данные или настройки';
  825. end if;
  826. if array_length(var_header_correction, 1) < var_index then
  827. raise exception 'Невозможно произвести расчет по высоте. Некорректные исходные данные или настройки';
  828. end if;
  829. raise notice '| Высота | Поправка |';
  830. raise notice '|----------|-----------|';
  831. for var_row in
  832. select t1.height, t2.* from calc_height_correction as t1
  833. inner join public.calc_wind_speed_height_correction as t2
  834. on t2.calc_height_id = t1.id
  835. where
  836. t1.measurment_type_id = par_measurement_type_id loop
  837. -- Получаем индекс
  838. var_header_index := abs(var_index % 10);
  839. var_table := var_row.values;
  840. -- Поправка на скорость среднего ветра
  841. var_deviation:= var_table[ var_header_index ];
  842. select '|' || lpad(var_row.height::text, 10, ' ') || '|' || lpad(var_deviation::text, 11,' ') || '|'
  843. into
  844. var_table_row;
  845. raise notice '%', var_table_row;
  846. var_correction.calc_height_id := var_row.calc_height_id;
  847. var_correction.height := var_row.height;
  848. -- Скорость среднего ветра
  849. var_correction.wind_speed_deviation := var_deviation;
  850. -- Приращение среднего ветра относительно направления приземного ветра
  851. var_correction.wind_deviation = var_row.delta;
  852. par_corrections := array_append(par_corrections, var_correction);
  853. end loop;
  854. raise notice '|----------|-----------|';
  855. end;
  856. $body$;
  857. raise notice 'Структура сформирована успешно';
  858. end $$;
  859. -- //////////////////////////////////////////////////////////////////////////////
  860. -- Проверка расчета
  861. do $$
  862. declare
  863. var_pressure_value numeric(8,2) default 0;
  864. var_temperature_value numeric(8,2) default 0;
  865. var_period text;
  866. var_pressure text;
  867. var_height text;
  868. var_temperature text;
  869. begin
  870. var_pressure_value := round(public.fn_calc_header_pressure(743));
  871. var_temperature_value := round( public.fn_calc_header_temperature(3));
  872. select
  873. -- Дата
  874. public.fn_calc_header_period(now()) as "ДДЧЧМ",
  875. --Высота расположения метеопоста над уровнем моря.
  876. lpad( 340::text, 4, '0' ) as "ВВВВ",
  877. -- Отклонение наземного давления атмосферы
  878. lpad(
  879. case when var_pressure_value < 0 then
  880. '5'
  881. else ''
  882. end ||
  883. lpad ( abs((var_pressure_value)::int)::text,2,'0')
  884. , 3, '0') as "БББ",
  885. -- Отклонение приземной виртуальной температуры
  886. lpad(
  887. case when var_temperature_value < 0 then
  888. '5'
  889. else
  890. ''
  891. end ||
  892. (abs(var_temperature_value)::int)::text
  893. , 2,'0') as "TT"
  894. into
  895. var_period, var_height, var_pressure, var_temperature;
  896. raise notice '==============================';
  897. raise notice 'Пример расчета метео приближенный';
  898. raise notice 'ДДЧЧМ %, ВВВВ %, БББ % , TT %', var_period, var_height, var_pressure, var_temperature;
  899. end $$;
  900. -- Проверка входных параметров
  901. do $$
  902. declare
  903. var_result public.check_result;
  904. begin
  905. raise notice '=====================================';
  906. raise notice 'Проверка работы функции [fn_check_input_params]';
  907. raise notice 'Положительный сценарий';
  908. -- Корректный вариант
  909. var_result := public.fn_check_input_params(par_height => 400, par_temperature => 23, par_pressure => 740, par_wind_direction => 5, par_wind_speed => 5, par_bullet_demolition_range => 5 );
  910. if var_result.is_check != True then
  911. raise notice '-> Проверка не пройдена!';
  912. else
  913. raise notice '-> Проверка пройдена';
  914. end if;
  915. raise notice 'Сообщени: %', var_result.error_message;
  916. -- Некорректный вариант
  917. var_result := public.fn_check_input_params(par_height => -400, par_temperature => 23, par_pressure => 740, par_wind_direction => 5, par_wind_speed => 5, par_bullet_demolition_range => 5 );
  918. raise notice 'Отрицательный сценарий';
  919. if var_result.is_check != False then
  920. raise notice '-> Проверка не пройдена!';
  921. else
  922. raise notice '-> Проверка пройдена';
  923. end if;
  924. raise notice 'Сообщение: %', var_result.error_message;
  925. raise notice '=====================================';
  926. end $$;
  927. -- Проверка расчета поправок по высоте для температуры
  928. do $$
  929. declare
  930. var_temperature_corrections temperature_correction[];
  931. var_wind_speed_corrections wind_direction_correction[];
  932. begin
  933. raise notice 'Проверка расчета поправок к температуре по высоте [sp_calc_temperature_deviation]';
  934. call public.sp_calc_temperature_deviation( par_temperature_correction => 3::numeric, par_measurement_type_id => 2::integer,
  935. par_corrections => var_temperature_corrections::public.temperature_correction[]);
  936. raise notice 'Результат расчета для корректировки по температуре 3 и типа оборудования 2: % ', var_temperature_corrections;
  937. raise notice '=====================================';
  938. raise notice 'Проверка расчета поправок к скорости ветра и направления [sp_calc_wind_speed_deviation]';
  939. call public.sp_calc_wind_speed_deviation( par_bullet_demolition_range => 14::numeric, par_measurement_type_id => 2::integer,
  940. par_corrections => var_wind_speed_corrections::public.wind_direction_correction[]);
  941. raise notice 'Результат расчета для сноса пуль 14 и типа оборудования 2: % ', var_wind_speed_corrections;
  942. raise notice '=====================================';
  943. end $$;
  944. -- Генерация тестовых данных
  945. do $$
  946. declare
  947. var_position integer;
  948. var_emploee_ids integer[];
  949. var_emploee_quantity integer default 5;
  950. var_min_rank integer;
  951. var_max_rank integer;
  952. var_emploee_id integer;
  953. var_current_emploee_id integer;
  954. var_index integer;
  955. var_measure_type_id integer;
  956. var_measure_input_data_id integer;
  957. begin
  958. -- Определяем макс дипазон по должностям
  959. select min(id), max(id)
  960. into var_min_rank,var_max_rank
  961. from public.military_ranks;
  962. -- Формируем список пользователей
  963. for var_position in 1 .. var_emploee_quantity loop
  964. insert into public.employees(name, birthday, military_rank_id )
  965. select
  966. fn_get_random_text(25), -- name
  967. fn_get_random_timestamp('1978-01-01','2000-01-01'), -- birthday
  968. fn_get_randon_integer(var_min_rank, var_max_rank) -- military_rank_id
  969. ;
  970. select id into var_emploee_id from public.employees order by id desc limit 1;
  971. var_emploee_ids := var_emploee_ids || var_emploee_id;
  972. end loop;
  973. raise notice 'Сформированы тестовые пользователи %', var_emploee_ids;
  974. -- Формируем для каждого по 100 измерений
  975. foreach var_current_emploee_id in ARRAY var_emploee_ids LOOP
  976. for var_index in 1 .. 100 loop
  977. var_measure_type_id := fn_get_randon_integer(1,2);
  978. insert into public.measurment_input_params(measurment_type_id, height, temperature, pressure, wind_direction, wind_speed)
  979. select
  980. var_measure_type_id,
  981. fn_get_randon_integer(0,600)::numeric(8,2), -- height
  982. fn_get_randon_integer(0, 50)::numeric(8,2), -- temperature
  983. fn_get_randon_integer(500, 850)::numeric(8,2), -- pressure
  984. fn_get_randon_integer(0,59)::numeric(8,2), -- ind_direction
  985. fn_get_randon_integer(0,59)::numeric(8,2) -- wind_speed
  986. ;
  987. select id into var_measure_input_data_id from measurment_input_params order by id desc limit 1;
  988. insert into public.measurment_baths( emploee_id, measurment_input_param_id, started)
  989. select
  990. var_current_emploee_id,
  991. var_measure_input_data_id,
  992. fn_get_random_timestamp('2025-02-01 00:00', '2025-02-05 00:00')
  993. ;
  994. end loop;
  995. end loop;
  996. raise notice 'Набор тестовых данных сформирован успешно';
  997. end $$;
  998. create view vw_report_fails_statistics
  999. as
  1000. -- Отчет: Статистика ошибок при проведении измерений
  1001. -- ФИО, должность, количество измерений, количество ошибок
  1002. with emploee_cte as
  1003. (
  1004. -- ФИО | Должность
  1005. select
  1006. t1.id , t1.name as user_name, t2.description as position
  1007. from public.employees as t1
  1008. inner join public.military_ranks as t2 on t1.military_rank_id = t2.id
  1009. ),
  1010. measurements_cte as
  1011. (
  1012. -- Кол-во измерений
  1013. select count(*) as quantity, emploee_id
  1014. from public.measurment_input_params as t1
  1015. inner join public.measurment_baths as t2 on t2.measurment_input_param_id = t1.id
  1016. group by emploee_id
  1017. ),
  1018. fails_cte as
  1019. (
  1020. -- Количество ошибочных данных
  1021. select
  1022. count(*) as quantity_fails,
  1023. emploee_id
  1024. from public.measurment_input_params as t1
  1025. inner join public.measurment_baths as t2 on t2.measurment_input_param_id = t1.id
  1026. where
  1027. (public.fn_check_input_params(height, temperature, pressure, wind_direction, wind_speed, bullet_demolition_range)::public.check_result).is_check = False
  1028. group by emploee_id
  1029. )
  1030. -- Основной запрос
  1031. select
  1032. user_name, position, coalesce(quantity,0) as quantity, coalesce(quantity_fails,0) as quantity_fails
  1033. from emploee_cte as t1
  1034. left join measurements_cte as t2 on t1.id = t2.emploee_id
  1035. left join fails_cte as t3 on t1.id = t3.emploee_id
  1036. order by coalesce(quantity_fails,0) desc;
  1037. create view vw_report_fails_height_statistics
  1038. as
  1039. -- Отчет: "Самая эффективная высота измерения"
  1040. -- | ФИО пользователя | Звание | Мин. высота метеопоста | Макс. высота метепоста | Всего измерений | Из них ошибочны |
  1041. with emploee_cte as
  1042. (
  1043. -- ФИО | Должность
  1044. select
  1045. t1.id , t1.name as user_name, t2.description as position
  1046. from public.employees as t1
  1047. inner join public.military_ranks as t2 on t1.military_rank_id = t2.id
  1048. ),
  1049. measurements_cte as
  1050. (
  1051. -- Кол-во измерений
  1052. select count(*) as quantity, emploee_id
  1053. from public.measurment_input_params as t1
  1054. inner join public.measurment_baths as t2 on t2.measurment_input_param_id = t1.id
  1055. group by emploee_id
  1056. ),
  1057. fails_cte as
  1058. (
  1059. -- Количество ошибочных данных
  1060. select
  1061. count(*) as quantity_fails,
  1062. emploee_id
  1063. from public.measurment_input_params as t1
  1064. inner join public.measurment_baths as t2 on t2.measurment_input_param_id = t1.id
  1065. where
  1066. (public.fn_check_input_params(height, temperature, pressure, wind_direction, wind_speed, bullet_demolition_range)::public.check_result).is_check = False
  1067. group by emploee_id
  1068. ),
  1069. measurments_height_cte as
  1070. (
  1071. -- Статистика по высотам
  1072. select min(height) as min_height, max(height) as max_height, emploee_id
  1073. from public.measurment_input_params as t1
  1074. inner join public.measurment_baths as t2 on t2.measurment_input_param_id = t1.id
  1075. group by emploee_id
  1076. )
  1077. -- Основной запрос
  1078. select
  1079. user_name, position, coalesce(quantity,0) as quantity, coalesce(quantity_fails,0) as quantity_fails,
  1080. coalesce(min_height, 0) as min_height, coalesce(max_height, 0) as max_height
  1081. from emploee_cte as t1
  1082. left join measurements_cte as t2 on t1.id = t2.emploee_id
  1083. left join fails_cte as t3 on t1.id = t3.emploee_id
  1084. left join measurments_height_cte as t4 on t1.id = t4.emploee_id
  1085. order by coalesce(quantity_fails,0) asc, coalesce(min_height, 0) asc ;
  1086. -- Проверка отчета
  1087. select * from vw_report_fails_height_statistics