4.sql 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  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. WITH user_measurements AS (
  99. SELECT
  100. u.name AS "ФИО",
  101. mr.name AS "Должность",
  102. COUNT(b.id) AS "Количество измерений",
  103. SUM(CASE WHEN validate_measurement(p.temperature, p.pressure, p.wind_direction) IS NULL THEN 1 ELSE 0 END) AS "Количество ошибочных данных"
  104. FROM users u
  105. JOIN ranks mr ON u.rank_id = mr.id
  106. JOIN measurement_batch b ON u.id = b.user_id
  107. JOIN measurement_params p ON p.measurement_batch_id = b.id
  108. GROUP BY u.name, mr.name
  109. )
  110. SELECT
  111. "ФИО",
  112. "Должность",
  113. "Количество измерений",
  114. "Количество ошибочных данных"
  115. FROM user_measurements
  116. ORDER BY "Количество ошибочных данных" DESC;