Обновить amountCalculating.sql
This commit is contained in:
@@ -0,0 +1,478 @@
|
||||
WITH
|
||||
-- 1. Получаем все проверки ICMP за период
|
||||
checks AS (
|
||||
SELECT
|
||||
h.host AS host_name,
|
||||
COALESCE(h.name, h.host) AS visible_name,
|
||||
COALESCE(hinv."name", 'не указан') AS equipment_type,
|
||||
COALESCE(hinv.notes, '') AS object_number,
|
||||
CASE
|
||||
WHEN hinv.location_lat IS NOT NULL AND hinv.location_lon IS NOT NULL
|
||||
AND hinv.location_lat != '' AND hinv.location_lon != ''
|
||||
THEN hinv.location_lat || ' ' || hinv.location_lon
|
||||
WHEN hinv.location_lat IS NOT NULL AND hinv.location_lat != ''
|
||||
THEN hinv.location_lat
|
||||
WHEN hinv.location_lon IS NOT NULL AND hinv.location_lon != ''
|
||||
THEN hinv.location_lon
|
||||
ELSE ''
|
||||
END AS coordinates,
|
||||
TO_TIMESTAMP(hx.clock) AT TIME ZONE 'Europe/Moscow' AS check_time,
|
||||
hx.value AS status
|
||||
FROM hosts h
|
||||
INNER JOIN items i
|
||||
ON i.hostid = h.hostid
|
||||
AND i.key_ = 'icmpping'
|
||||
AND i.status = 0
|
||||
AND i.value_type = 3
|
||||
INNER JOIN history_uint hx
|
||||
ON hx.itemid = i.itemid
|
||||
LEFT JOIN host_inventory hinv
|
||||
ON hinv.hostid = h.hostid
|
||||
WHERE
|
||||
h.status = 0
|
||||
AND h.host NOT LIKE '%WiMAX'
|
||||
AND CAST(NULLIF(REGEXP_REPLACE(hinv.notes, 'ОБЪЕКТ №\s*', '', 'g'), '') AS INTEGER)
|
||||
BETWEEN 1 AND 85
|
||||
AND TO_TIMESTAMP(hx.clock) >= TO_DATE(${start_dt}, 'yyyymmdd') - INTERVAL '1 day'
|
||||
AND TO_TIMESTAMP(hx.clock) <= TO_DATE(${end_dt}, 'yyyymmdd') + INTERVAL '1 day'
|
||||
),
|
||||
|
||||
-- 2. Добавляем предыдущий статус
|
||||
checks_with_prev AS (
|
||||
SELECT
|
||||
*,
|
||||
LAG(status) OVER (PARTITION BY host_name ORDER BY check_time) AS prev_status,
|
||||
COALESCE(LEAD(check_time) OVER (PARTITION BY host_name ORDER BY check_time), NOW()) AS next_check_time
|
||||
FROM checks
|
||||
),
|
||||
|
||||
-- 3. Определяем моменты смены статуса
|
||||
status_changes AS (
|
||||
SELECT
|
||||
host_name,
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates,
|
||||
check_time,
|
||||
status,
|
||||
prev_status,
|
||||
CASE
|
||||
WHEN DATE(next_check_time) > DATE(check_time)
|
||||
THEN DATE_TRUNC('day', check_time) + INTERVAL '1 day'
|
||||
ELSE next_check_time
|
||||
END AS next_check_time,
|
||||
CASE WHEN status != prev_status THEN 1 ELSE 0 END AS is_start
|
||||
FROM checks_with_prev
|
||||
UNION ALL
|
||||
SELECT
|
||||
host_name,
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates,
|
||||
DATE_TRUNC('day', next_check_time) + INTERVAL '00:00:00' AS check_time,
|
||||
status,
|
||||
prev_status,
|
||||
next_check_time,
|
||||
1 AS is_start
|
||||
FROM checks_with_prev
|
||||
WHERE DATE(next_check_time) > DATE(check_time)
|
||||
),
|
||||
|
||||
-- 4. Нумеруем интервалы
|
||||
intervals AS (
|
||||
SELECT
|
||||
*,
|
||||
SUM(is_start) OVER (PARTITION BY host_name ORDER BY check_time) AS interval_id
|
||||
FROM status_changes
|
||||
WHERE status IS NOT NULL
|
||||
AND DATE_TRUNC('day', check_time) >= TO_DATE(${start_dt}, 'yyyymmdd')
|
||||
AND DATE_TRUNC('day', check_time) <= TO_DATE(${end_dt}, 'yyyymmdd')
|
||||
),
|
||||
|
||||
-- 5. Группируем интервалы
|
||||
grouped_intervals AS (
|
||||
SELECT
|
||||
host_name,
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates,
|
||||
MIN(check_time) AS check_time,
|
||||
MAX(next_check_time) AS next_check_time,
|
||||
MAX(status) AS status
|
||||
FROM intervals
|
||||
GROUP BY
|
||||
host_name,
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates,
|
||||
interval_id
|
||||
),
|
||||
|
||||
-- 6. Посуточная агрегация (часы доступности)
|
||||
daily_stats_raw AS (
|
||||
SELECT
|
||||
host_name,
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates,
|
||||
DATE(check_time) AS check_date,
|
||||
ROUND(
|
||||
SUM(CASE WHEN status = 1 THEN EXTRACT(EPOCH FROM (next_check_time - check_time)) / 3600 ELSE 0 END) * 2
|
||||
) / 2 AS available_hours
|
||||
FROM grouped_intervals
|
||||
GROUP BY
|
||||
host_name,
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates,
|
||||
DATE(check_time)
|
||||
),
|
||||
|
||||
-- 7. Статистика по периферии (для маршрутизаторов)
|
||||
peripheral_stats AS (
|
||||
SELECT
|
||||
object_number,
|
||||
check_date,
|
||||
MAX(CASE WHEN available_hours > 12 THEN 1 ELSE 0 END) AS has_peripheral_work
|
||||
FROM daily_stats_raw
|
||||
WHERE equipment_type NOT LIKE 'Маршрутизатор%'
|
||||
GROUP BY object_number, check_date
|
||||
),
|
||||
|
||||
-- 8. Собираем все дни месяца
|
||||
all_dates AS (
|
||||
SELECT generate_series(
|
||||
TO_DATE(${start_dt}, 'yyyymmdd'),
|
||||
TO_DATE(${end_dt}, 'yyyymmdd'),
|
||||
'1 day'::interval
|
||||
)::date AS check_date
|
||||
),
|
||||
|
||||
-- 9. Кросс-джойн для каждого оборудования
|
||||
equipment_dates AS (
|
||||
SELECT DISTINCT
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates,
|
||||
ad.check_date
|
||||
FROM daily_stats_raw d
|
||||
CROSS JOIN all_dates ad
|
||||
),
|
||||
|
||||
-- 10. Присоединяем доступность ко всем дням
|
||||
daily_stats_full AS (
|
||||
SELECT
|
||||
ed.visible_name,
|
||||
ed.equipment_type,
|
||||
ed.object_number,
|
||||
ed.coordinates,
|
||||
ed.check_date,
|
||||
COALESCE(dsr.available_hours, 0) AS available_hours
|
||||
FROM equipment_dates ed
|
||||
LEFT JOIN daily_stats_raw dsr
|
||||
ON dsr.visible_name = ed.visible_name
|
||||
AND dsr.check_date = ed.check_date
|
||||
),
|
||||
|
||||
-- 11. Финальная агрегация по оборудованию
|
||||
equipment_summary AS (
|
||||
SELECT
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates,
|
||||
STRING_AGG(
|
||||
CASE
|
||||
WHEN available_hours > 0 THEN TO_CHAR(check_date, 'DD.MM') || ':' || available_hours::TEXT
|
||||
ELSE NULL
|
||||
END,
|
||||
'; ' ORDER BY check_date
|
||||
) AS daily_schedule,
|
||||
COUNT(CASE WHEN available_hours > 12 THEN 1 END) AS days_gt_12h,
|
||||
COUNT(CASE WHEN available_hours <= 12 AND available_hours > 0 THEN 1 END) AS days_le_12h,
|
||||
ROUND(AVG(available_hours), 3) AS avg_hours,
|
||||
-- Суммарные сутки доступности (факт) - по каждому устройству
|
||||
ROUND(SUM(available_hours) / 24, 0) AS total_days_per_device
|
||||
FROM daily_stats_full
|
||||
GROUP BY
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates
|
||||
),
|
||||
|
||||
-- 12. Отдельно считаем работу маршрутизаторов
|
||||
router_work AS (
|
||||
SELECT
|
||||
d.object_number,
|
||||
COUNT(DISTINCT d.check_date) AS router_work_days
|
||||
FROM daily_stats_raw d
|
||||
INNER JOIN peripheral_stats p
|
||||
ON p.object_number = d.object_number
|
||||
AND p.check_date = d.check_date
|
||||
WHERE d.equipment_type LIKE 'Маршрутизатор%'
|
||||
AND p.has_peripheral_work = 1
|
||||
GROUP BY d.object_number
|
||||
),
|
||||
|
||||
-- 13. Определяем этап
|
||||
stages AS (
|
||||
SELECT DISTINCT
|
||||
object_number,
|
||||
CASE
|
||||
WHEN object_number IN ('4','28','30','31','34','36','40','42','55','57','58','62','63','64','67','68','69','76','81','82','85') THEN '1 этап'
|
||||
WHEN object_number IN ('1','9','12','27','35','38','41','43','44','48','49','51','53','54','60','65','77','84') THEN '2 этап'
|
||||
ELSE '3 этап'
|
||||
END AS stage
|
||||
FROM equipment_summary
|
||||
),
|
||||
|
||||
-- 14. Подготавливаем данные для PIVOT-агрегации
|
||||
daily_pivot AS (
|
||||
SELECT
|
||||
visible_name,
|
||||
equipment_type,
|
||||
object_number,
|
||||
coordinates,
|
||||
check_date,
|
||||
available_hours
|
||||
FROM daily_stats_full
|
||||
),
|
||||
|
||||
-- 15. СВОДНАЯ ТАБЛИЦА по типам оборудования
|
||||
summary_by_type AS (
|
||||
SELECT
|
||||
equipment_type,
|
||||
-- оборудование-сутки факт (сумма по всем устройствам типа)
|
||||
ROUND(SUM(total_days_per_device), 0) AS fact_days,
|
||||
-- Кол-во оборудования (статичное из Excel)
|
||||
CASE
|
||||
WHEN equipment_type LIKE 'Видеокамера%' THEN 85
|
||||
WHEN equipment_type LIKE 'Детектор%' THEN 79
|
||||
WHEN equipment_type LIKE 'Метеостанция%' THEN 30
|
||||
WHEN equipment_type LIKE 'Маршрутизатор%' THEN 88
|
||||
WHEN equipment_type LIKE 'Коммутационный шкаф%' THEN 88
|
||||
WHEN equipment_type LIKE 'Криптошлюз%' THEN 88
|
||||
ELSE 0
|
||||
END AS equipment_count,
|
||||
-- оборудование-сутки план = 30 дней × количество оборудования
|
||||
CASE
|
||||
WHEN equipment_type LIKE 'Видеокамера%' THEN 30 * 85
|
||||
WHEN equipment_type LIKE 'Детектор%' THEN 30 * 79
|
||||
WHEN equipment_type LIKE 'Метеостанция%' THEN 30 * 30
|
||||
WHEN equipment_type LIKE 'Маршрутизатор%' THEN 30 * 88
|
||||
WHEN equipment_type LIKE 'Коммутационный шкаф%' THEN 30 * 88
|
||||
WHEN equipment_type LIKE 'Криптошлюз%' THEN 30 * 88
|
||||
ELSE 0
|
||||
END AS plan_days,
|
||||
-- оборудование-сутки процент = факт / план
|
||||
ROUND(SUM(total_days_per_device) /
|
||||
CASE
|
||||
WHEN equipment_type LIKE 'Видеокамера%' THEN 30 * 85
|
||||
WHEN equipment_type LIKE 'Детектор%' THEN 30 * 79
|
||||
WHEN equipment_type LIKE 'Метеостанция%' THEN 30 * 30
|
||||
WHEN equipment_type LIKE 'Маршрутизатор%' THEN 30 * 88
|
||||
WHEN equipment_type LIKE 'Коммутационный шкаф%' THEN 30 * 88
|
||||
WHEN equipment_type LIKE 'Криптошлюз%' THEN 30 * 88
|
||||
ELSE 1
|
||||
END, 9) AS percent,
|
||||
-- Тариф в сутки (статичный из Excel)
|
||||
CASE
|
||||
WHEN equipment_type LIKE 'Видеокамера%' THEN 43038.15
|
||||
WHEN equipment_type LIKE 'Детектор%' THEN 91293.59
|
||||
WHEN equipment_type LIKE 'Метеостанция%' THEN 53323.20
|
||||
WHEN equipment_type LIKE 'Маршрутизатор%' THEN 8868.36
|
||||
WHEN equipment_type LIKE 'Коммутационный шкаф%' THEN 4514.60
|
||||
WHEN equipment_type LIKE 'Криптошлюз%' THEN 10883.72
|
||||
ELSE 0
|
||||
END AS daily_rate,
|
||||
-- Итоговая сумма = Тариф × Кол-во дней в месяце × процент
|
||||
ROUND(
|
||||
CASE
|
||||
WHEN equipment_type LIKE 'Видеокамера%' THEN 43038.15
|
||||
WHEN equipment_type LIKE 'Детектор%' THEN 91293.59
|
||||
WHEN equipment_type LIKE 'Метеостанция%' THEN 53323.20
|
||||
WHEN equipment_type LIKE 'Маршрутизатор%' THEN 8868.36
|
||||
WHEN equipment_type LIKE 'Коммутационный шкаф%' THEN 4514.60
|
||||
WHEN equipment_type LIKE 'Криптошлюз%' THEN 10883.72
|
||||
ELSE 0
|
||||
END * 30 *
|
||||
(SUM(total_days_per_device) /
|
||||
CASE
|
||||
WHEN equipment_type LIKE 'Видеокамера%' THEN 30 * 85
|
||||
WHEN equipment_type LIKE 'Детектор%' THEN 30 * 79
|
||||
WHEN equipment_type LIKE 'Метеостанция%' THEN 30 * 30
|
||||
WHEN equipment_type LIKE 'Маршрутизатор%' THEN 30 * 88
|
||||
WHEN equipment_type LIKE 'Коммутационный шкаф%' THEN 30 * 88
|
||||
WHEN equipment_type LIKE 'Криптошлюз%' THEN 30 * 88
|
||||
ELSE 1
|
||||
END),
|
||||
2
|
||||
) AS total_amount
|
||||
FROM equipment_summary
|
||||
GROUP BY equipment_type
|
||||
)
|
||||
|
||||
-- 16. Итоговый SELECT (детальный отчёт)
|
||||
SELECT
|
||||
'ДЕТАЛЬНЫЙ ОТЧЁТ' AS section,
|
||||
s.stage AS "Этап",
|
||||
s.object_number AS "№ объекта",
|
||||
e.equipment_type AS "Вид оборудования",
|
||||
e.coordinates AS "Координаты",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-01' THEN d.available_hours END) AS "01.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-02' THEN d.available_hours END) AS "02.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-03' THEN d.available_hours END) AS "03.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-04' THEN d.available_hours END) AS "04.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-05' THEN d.available_hours END) AS "05.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-06' THEN d.available_hours END) AS "06.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-07' THEN d.available_hours END) AS "07.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-08' THEN d.available_hours END) AS "08.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-09' THEN d.available_hours END) AS "09.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-10' THEN d.available_hours END) AS "10.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-11' THEN d.available_hours END) AS "11.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-12' THEN d.available_hours END) AS "12.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-13' THEN d.available_hours END) AS "13.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-14' THEN d.available_hours END) AS "14.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-15' THEN d.available_hours END) AS "15.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-16' THEN d.available_hours END) AS "16.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-17' THEN d.available_hours END) AS "17.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-18' THEN d.available_hours END) AS "18.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-19' THEN d.available_hours END) AS "19.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-20' THEN d.available_hours END) AS "20.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-21' THEN d.available_hours END) AS "21.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-22' THEN d.available_hours END) AS "22.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-23' THEN d.available_hours END) AS "23.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-24' THEN d.available_hours END) AS "24.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-25' THEN d.available_hours END) AS "25.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-26' THEN d.available_hours END) AS "26.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-27' THEN d.available_hours END) AS "27.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-28' THEN d.available_hours END) AS "28.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-29' THEN d.available_hours END) AS "29.06",
|
||||
MAX(CASE WHEN d.check_date = DATE '2026-06-30' THEN d.available_hours END) AS "30.06",
|
||||
e.days_gt_12h AS "Дней >12 ч",
|
||||
e.days_le_12h AS "Дней ≤12 ч",
|
||||
e.avg_hours AS "Среднее часов",
|
||||
COALESCE(rw.router_work_days, 0) AS "Маршрутизатор работа в днях"
|
||||
FROM equipment_summary e
|
||||
LEFT JOIN stages s ON s.object_number = e.object_number
|
||||
LEFT JOIN daily_pivot d
|
||||
ON d.visible_name = e.visible_name
|
||||
AND d.equipment_type = e.equipment_type
|
||||
AND d.object_number = e.object_number
|
||||
AND d.coordinates = e.coordinates
|
||||
LEFT JOIN router_work rw ON rw.object_number = e.object_number
|
||||
WHERE e.daily_schedule IS NOT NULL
|
||||
GROUP BY
|
||||
s.stage,
|
||||
s.object_number,
|
||||
e.equipment_type,
|
||||
e.coordinates,
|
||||
e.days_gt_12h,
|
||||
e.days_le_12h,
|
||||
e.avg_hours,
|
||||
rw.router_work_days
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 17. СВОДНАЯ ТАБЛИЦА (как в Excel)
|
||||
SELECT
|
||||
'СВОДНАЯ' AS section,
|
||||
'' AS "Этап",
|
||||
'' AS "№ объекта",
|
||||
s.equipment_type AS "Вид оборудования",
|
||||
'' AS "Координаты",
|
||||
NULL AS "01.06",
|
||||
NULL AS "02.06",
|
||||
NULL AS "03.06",
|
||||
NULL AS "04.06",
|
||||
NULL AS "05.06",
|
||||
NULL AS "06.06",
|
||||
NULL AS "07.06",
|
||||
NULL AS "08.06",
|
||||
NULL AS "09.06",
|
||||
NULL AS "10.06",
|
||||
NULL AS "11.06",
|
||||
NULL AS "12.06",
|
||||
NULL AS "13.06",
|
||||
NULL AS "14.06",
|
||||
NULL AS "15.06",
|
||||
NULL AS "16.06",
|
||||
NULL AS "17.06",
|
||||
NULL AS "18.06",
|
||||
NULL AS "19.06",
|
||||
NULL AS "20.06",
|
||||
NULL AS "21.06",
|
||||
NULL AS "22.06",
|
||||
NULL AS "23.06",
|
||||
NULL AS "24.06",
|
||||
NULL AS "25.06",
|
||||
NULL AS "26.06",
|
||||
NULL AS "27.06",
|
||||
NULL AS "28.06",
|
||||
NULL AS "29.06",
|
||||
NULL AS "30.06",
|
||||
-- Колонки сводной таблицы в правильном порядке
|
||||
s.fact_days AS "оборудование-сутки факт",
|
||||
s.plan_days AS "оборудование-сутки план",
|
||||
s.percent AS "оборудование-сутки процент",
|
||||
s.equipment_count AS "Кол-во оборудования",
|
||||
s.daily_rate AS "Тариф в сутки по договору ИТСР",
|
||||
s.total_amount AS "Итоговая сумма к начислению"
|
||||
FROM summary_by_type s
|
||||
|
||||
UNION ALL
|
||||
|
||||
-- 18. ИТОГОВАЯ СТРОКА
|
||||
SELECT
|
||||
'ИТОГО' AS section,
|
||||
'' AS "Этап",
|
||||
'' AS "№ объекта",
|
||||
'Итоговая Сумма' AS "Вид оборудования",
|
||||
'' AS "Координаты",
|
||||
NULL AS "01.06",
|
||||
NULL AS "02.06",
|
||||
NULL AS "03.06",
|
||||
NULL AS "04.06",
|
||||
NULL AS "05.06",
|
||||
NULL AS "06.06",
|
||||
NULL AS "07.06",
|
||||
NULL AS "08.06",
|
||||
NULL AS "09.06",
|
||||
NULL AS "10.06",
|
||||
NULL AS "11.06",
|
||||
NULL AS "12.06",
|
||||
NULL AS "13.06",
|
||||
NULL AS "14.06",
|
||||
NULL AS "15.06",
|
||||
NULL AS "16.06",
|
||||
NULL AS "17.06",
|
||||
NULL AS "18.06",
|
||||
NULL AS "19.06",
|
||||
NULL AS "20.06",
|
||||
NULL AS "21.06",
|
||||
NULL AS "22.06",
|
||||
NULL AS "23.06",
|
||||
NULL AS "24.06",
|
||||
NULL AS "25.06",
|
||||
NULL AS "26.06",
|
||||
NULL AS "27.06",
|
||||
NULL AS "28.06",
|
||||
NULL AS "29.06",
|
||||
NULL AS "30.06",
|
||||
SUM(s.fact_days) AS "оборудование-сутки факт",
|
||||
SUM(s.plan_days) AS "оборудование-сутки план",
|
||||
ROUND(SUM(s.fact_days) / SUM(s.plan_days), 9) AS "оборудование-сутки процент",
|
||||
SUM(s.equipment_count) AS "Кол-во оборудования",
|
||||
NULL AS "Тариф в сутки по договору ИТСР",
|
||||
SUM(s.total_amount) AS "Итоговая сумма к начислению"
|
||||
FROM summary_by_type s
|
||||
|
||||
ORDER BY section DESC, "Этап", "№ объекта", "Вид оборудования";
|
||||
Reference in New Issue
Block a user