4.sql 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  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. t0 NUMERIC;
  59. delta_t NUMERIC;
  60. deviation_value NUMERIC;
  61. deviation_ten NUMERIC;
  62. deviation_unit NUMERIC;
  63. row_data RECORD;
  64. BEGIN
  65. t0 := temperature + (select value from numeric_constants where key = 'dtv' limit 1);
  66. raise notice 't0 %', t0;
  67. delta_t := t0 - (select value from numeric_constants where key = 'mp' limit 1);
  68. delta_t := ROUND(delta_t);
  69. FOR row_data IN SELECT * FROM average_deviations_temperature LOOP
  70. deviation_ten := (delta_t / 10) * 10;
  71. deviation_unit := delta_t % 10;
  72. deviation_ten := deviation_ten - deviation_unit;
  73. IF delta_t < 0 THEN
  74. deviation_value := row_data.negative_values[abs(deviation_ten)] +
  75. row_data.negative_values[abs(deviation_unit)];
  76. ELSE
  77. deviation_value := row_data.positive_values[abs(deviation_ten)] +
  78. row_data.positive_values[abs(deviation_unit)];
  79. END IF;
  80. height := row_data.height;
  81. deviation := deviation_value;
  82. RETURN NEXT;
  83. END LOOP;
  84. END;
  85. $$ LANGUAGE plpgsql;
  86. select
  87. u.name as "ФИО",
  88. mr.name as "Должность",
  89. COUNT(b.id) as "Количество измерений",
  90. SUM(case validate_measurement(p.temperature, p.pressure, p.wind_direction) when null then 1 else 0 end) as "Количество ошибочных данных"
  91. from users u
  92. join ranks mr on u.rank_id = mr.id
  93. join measurement_batch b on u.id = b.user_id
  94. join measurement_params p on p.measurement_batch_id = b.id
  95. group by u.name, mr.name
  96. order by "Количество ошибочных данных" desc;