4.sql 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. -- Таблица для расчета среднего
  2. CREATE TABLE average_deviations_temperature (
  3. height INT PRIMARY KEY, -- Высота
  4. negative_values NUMERIC[], -- Массив для отрицательных значений
  5. positive_values NUMERIC[] -- Массив для положительных значений
  6. );
  7. INSERT INTO average_deviations_temperature (height, negative_values, positive_values)
  8. VALUES
  9. (
  10. 200,
  11. ARRAY[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -20, -30, -40, -50],
  12. ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, NULL, NULL]
  13. ),
  14. (
  15. 400,
  16. ARRAY[-1, -2, -3, -4, -5, -6, -6, -7, -8, -9, -19, -29, -38, -48],
  17. ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, NULL, NULL]
  18. ),
  19. (
  20. 800,
  21. ARRAY[-1, -2, -3, -4, -5, -6, -6, -7, -7, -8, -18, -28, -37, -46],
  22. ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, NULL, NULL]
  23. ),
  24. (
  25. 1200,
  26. ARRAY[-1, -2, -3, -4, -4, -5, -5, -6, -7, -8, -17, -26, -35, -44],
  27. ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, NULL, NULL]
  28. ),
  29. (
  30. 1600,
  31. ARRAY[-1, -2, -3, -3, -4, -4, -5, -6, -7, -7, -17, -25, -34, -42],
  32. ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, NULL, NULL]
  33. ),
  34. (
  35. 2000,
  36. ARRAY[-1, -2, -3, -3, -4, -4, -5, -6, -6, -7, -16, -24, -32, -40],
  37. ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, NULL, NULL]
  38. ),
  39. (
  40. 2400,
  41. ARRAY[-1, -2, -2, -3, -4, -4, -5, -5, -6, -7, -15, -23, -31, -38],
  42. ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, NULL, NULL]
  43. ),
  44. (
  45. 3000,
  46. ARRAY[-1, -2, -2, -3, -4, -4, -4, -5, -5, -6, -15, -22, -30, -37],
  47. ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, NULL, NULL]
  48. ),
  49. (
  50. 4000,
  51. ARRAY[-1, -2, -2, -3, -4, -4, -4, -4, -5, -6, -14, -20, -27, -34],
  52. ARRAY[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 20, 30, NULL, NULL]
  53. ) on conflict do nothing;
  54. insert into numeric_constants("key", "value") values ('dtv', 0.3), ('mp', 15.9) ON CONFLICT DO NOTHING;
  55. CREATE OR REPLACE FUNCTION calculate_average_deviation(temperature NUMERIC)
  56. RETURNS TABLE(height INT, deviation NUMERIC) AS $$
  57. DECLARE
  58. dtv NUMERIC;
  59. mp NUMERIC;
  60. t0 NUMERIC;
  61. delta_t NUMERIC;
  62. deviation_value NUMERIC;
  63. deviation_ten NUMERIC;
  64. deviation_unit NUMERIC;
  65. row_data RECORD;
  66. BEGIN
  67. select value into dtv from numeric_constants where key = 'dtv' limit 1;
  68. select value into mp from numeric_constants where key = 'mp' limit 1;
  69. IF dtv IS NULL THEN
  70. dtv := 0.3;
  71. RAISE NOTICE 'Константа dtv не найдена, использовано значение 0.3';
  72. END IF;
  73. IF mp IS NULL THEN
  74. mp := 15.9;
  75. RAISE NOTICE 'Константа mp не найдена, использовано значение 15.9';
  76. END IF;
  77. t0 := temperature + dtv;
  78. raise notice 't0 %', t0;
  79. delta_t := t0 - mp;
  80. delta_t := ROUND(delta_t);
  81. FOR row_data IN SELECT * FROM average_deviations_temperature LOOP
  82. deviation_ten := (delta_t / 10) * 10;
  83. deviation_unit := delta_t % 10;
  84. deviation_ten := deviation_ten - deviation_unit;
  85. IF delta_t < 0 THEN
  86. deviation_value := row_data.negative_values[abs(deviation_ten)] +
  87. row_data.negative_values[abs(deviation_unit)];
  88. ELSE
  89. deviation_value := row_data.positive_values[abs(deviation_ten)] +
  90. row_data.positive_values[abs(deviation_unit)];
  91. END IF;
  92. height := row_data.height;
  93. deviation := deviation_value;
  94. RETURN NEXT;
  95. END LOOP;
  96. END;
  97. $$ LANGUAGE plpgsql;
  98. select concat, count(*)
  99. from (
  100. select *, validate_measurement(p.temperature, p.pressure, p.wind_direction), concat(r.name, ' ', u.name
  101. )
  102. from measurement_params p
  103. join measurement_batch b on b.id = p.measurement_batch_id
  104. join users u on u.id = b.user_id
  105. join ranks r on r.id = u.rank_id)
  106. where validate_measurement is null
  107. group by concat
  108. order by count(*) desc;