Oracle: объединить 2 набора результатов - PullRequest
0 голосов
/ 30 октября 2018

Я застрял, и мне нужен совет, как объединить 2 набора результатов в 1

Первый набор результатов имеет пороговые значения для разных точек монтирования. Для каждой точки монтирования имеется строка с пороговым значением, отличным от значения по умолчанию, например, «u01» - «u08». Пороговое значение по умолчанию для всех остальных точек монтирования находится в строке с пустым значением MOUNTPOINT.

HOSTNAME                       MOUNTPOINT             WARNING_PC CRITICAL_P
------------------------------ ---------------------- ---------- ----------
oracledatabase.domain.local                           20         5        <-- here is default
oracledatabase.domain.local    /opt/nfsshare/u01      20         19
oracledatabase.domain.local    /opt/nfsshare/u02      1.01       1
oracledatabase.domain.local    /opt/nfsshare/u03      1.01       1
oracledatabase.domain.local    /opt/nfsshare/u04      1.01       1
oracledatabase.domain.local    /opt/nfsshare/u05      1.01       1
oracledatabase.domain.local    /opt/nfsshare/u07      1.01       1
oracledatabase.domain.local    /opt/nfsshare/u08      1.01       1

Второй набор результатов содержит список всех точек монтирования

HOSTNAME                       MOUNTPOINT
------------------------------ ----------------------------------------
oracledatabase.domain.local    /
oracledatabase.domain.local    /boot
oracledatabase.domain.local    /dev
oracledatabase.domain.local    /opt/nfsshare/u01
oracledatabase.domain.local    /opt/nfsshare/u02
oracledatabase.domain.local    /opt/nfsshare/u03
oracledatabase.domain.local    /opt/nfsshare/u04
oracledatabase.domain.local    /opt/nfsshare/u05
oracledatabase.domain.local    /opt/nfsshare/u06
oracledatabase.domain.local    /opt/nfsshare/u07
oracledatabase.domain.local    /opt/nfsshare/u08
oracledatabase.domain.local    /opt/nfsshare/u09
oracledatabase.domain.local    /opt/nfsshare/u10
oracledatabase.domain.local    /opt/nfsshare/u11
oracledatabase.domain.local    /opt/nfsshare/u12
oracledatabase.domain.local    /opt/nfsshare/u13

Итак, мне нужно присоединиться к ним следующим образом: Если точка монтирования имеет пороговое значение в первом наборе результатов, используйте это значение. Если пороговое значение для точки монтирования отсутствует, используйте значение по умолчанию

HOSTNAME                       MOUNTPOINT           WARNING_PC CRITICAL_P
------------------------------ -------------------  ---------- ----------
oracledatabase.domain.local    /                    20         5
oracledatabase.domain.local    /boot                20         5
oracledatabase.domain.local    /dev                 20         5
oracledatabase.domain.local    /opt/nfsshare/u01    20         19
oracledatabase.domain.local    /opt/nfsshare/u02    1.01       1
oracledatabase.domain.local    /opt/nfsshare/u03    1.01       1
oracledatabase.domain.local    /opt/nfsshare/u04    1.01       1
oracledatabase.domain.local    /opt/nfsshare/u05    1.01       1
oracledatabase.domain.local    /opt/nfsshare/u06    20         5
oracledatabase.domain.local    /opt/nfsshare/u07    1.01       1
oracledatabase.domain.local    /opt/nfsshare/u08    1.01       1
oracledatabase.domain.local    /opt/nfsshare/u09    20         5
oracledatabase.domain.local    /opt/nfsshare/u10    20         5
oracledatabase.domain.local    /opt/nfsshare/u11    20         5
oracledatabase.domain.local    /opt/nfsshare/u12    20         5
oracledatabase.domain.local    /opt/nfsshare/u13    20         5

Добавлено через несколько часов. Похоже, я нашел решение. Но возможно, есть лучший подход

COL HOSTNAME2 FOR A30
COL MOUNTPOINT2 FOR A30 

WITH THRESHOLDS AS (
SELECT TARGET_NAME "HOSTNAME1",
       DECODE(LENGTH(REPLACE(KEY_VALUE,CHR(32))),NULL,'DEFAULT',KEY_VALUE) "MOUNTPOINT1",
       WARNING_THRESHOLD "WARNING_PCT",
       CRITICAL_THRESHOLD "CRITICAL_PCT"
FROM
       SYSMAN.MGMT$METRIC_COLLECTION
WHERE
       TARGET_TYPE = 'host' AND
       METRIC_NAME = 'Filesystems' AND
       METRIC_COLUMN = 'pctAvailable' AND TARGET_NAME='oracledatabase.domain.local'
),
MOUNTPOINTS AS (
SELECT ENTITY_NAME "HOSTNAME2",
       KEY_PART_1  "MOUNTPOINT2"
FROM 
       SYSMAN.GC$METRIC_VALUES_LATEST
WHERE
       METRIC_GROUP_LABEL = 'Filesystems' AND  METRIC_COLUMN_NAME = 'available'
       AND ENTITY_NAME='oracledatabase.domain.local'
)
-- Get list of matching mountpoints
SELECT HOSTNAME2, MOUNTPOINT2, WARNING_PCT, CRITICAL_PCT FROM (
SELECT * FROM MOUNTPOINTS INNER JOIN  THRESHOLDS ON 
MOUNTPOINTS.MOUNTPOINT2=THRESHOLDS.MOUNTPOINT1)
-- Union
UNION ALL
-- Get list mountpoints with default threshold
SELECT HOSTNAME2, MOUNTPOINT2, WARNING_PCT, CRITICAL_PCT FROM
(SELECT * FROM MOUNTPOINTS WHERE MOUNTPOINT2 NOT IN (SELECT MOUNTPOINT1 FROM THRESHOLDS)),
(SELECT * FROM THRESHOLDS WHERE MOUNTPOINT1='DEFAULT') 
ORDER BY 2;

HOSTNAME2                      MOUNTPOINT2                    WARNING_PC CRITICAL_PCT
------------------------------ ------------------------------ ---------- --------------------
oracledatabase.domain.local    /                              20         5
oracledatabase.domain.local    /boot                          20         5
oracledatabase.domain.local    /dev                           20         5
oracledatabase.domain.local    /opt/nfsshare/u01              20         19
oracledatabase.domain.local    /opt/nfsshare/u02              1.01       1
oracledatabase.domain.local    /opt/nfsshare/u03              1.01       1
oracledatabase.domain.local    /opt/nfsshare/u04              1.01       1
oracledatabase.domain.local    /opt/nfsshare/u05              1.01       1
oracledatabase.domain.local    /opt/nfsshare/u06              20         5
oracledatabase.domain.local    /opt/nfsshare/u07              1.01       1
oracledatabase.domain.local    /opt/nfsshare/u08              1.01       1
oracledatabase.domain.local    /opt/nfsshare/u09              20         5
oracledatabase.domain.local    /opt/nfsshare/u10              20         5
oracledatabase.domain.local    /opt/nfsshare/u11              20         5
oracledatabase.domain.local    /opt/nfsshare/u12              20         5
oracledatabase.domain.local    /opt/nfsshare/u13              20         5

16 rows selected.


Подробности на "rs." комментарий (только для меня для дальнейшей справки)


Без функции COALESCE легче понять, как она работает.

WITH THRESHOLDS AS (
SELECT TARGET_NAME "HOSTNAME1",
       KEY_VALUE "MOUNTPOINT1",
       WARNING_THRESHOLD "WARNING_PCT",
       CRITICAL_THRESHOLD "CRITICAL_PCT"
FROM
       SYSMAN.MGMT$METRIC_COLLECTION
WHERE
       TARGET_TYPE = 'host' AND
       METRIC_NAME = 'Filesystems' AND
       METRIC_COLUMN = 'pctAvailable' AND TARGET_NAME='oracledatabase.domain.local'
),
MOUNTPOINTS AS (
SELECT ENTITY_NAME "HOSTNAME2",
       KEY_PART_1  "MOUNTPOINT2"
FROM 
       SYSMAN.GC$METRIC_VALUES_LATEST
WHERE
       METRIC_GROUP_LABEL = 'Filesystems' AND  METRIC_COLUMN_NAME = 'available'
       AND ENTITY_NAME='oracledatabase.domain.local'
)
SELECT A.HOSTNAME2, A.MOUNTPOINT2, 
       T1.WARNING_PCT "WRN_THR",
       T2.WARNING_PCT "WRN_DFL", 
       T1.CRITICAL_PCT "CRT_THR", 
       T2.CRITICAL_PCT "CRT_DFL"
FROM MOUNTPOINTS A
LEFT OUTER JOIN THRESHOLDS T1 ON A.MOUNTPOINT2 = T1.MOUNTPOINT1 --match
JOIN THRESHOLDS T2 ON COALESCE(TRIM(T2.MOUNTPOINT1),'DEFAULT') = 'DEFAULT';

HOSTNAME2                      MOUNTPOINT2          WRN_THR WRN_DFL CRT_THR CRT_DFL
------------------------------ -------------------- ------- ------- ------- -------
oracledatabase.domain.local    /opt/nfsshare/u01    20      20      19      5
oracledatabase.domain.local    /opt/nfsshare/u02    1.01    20      1       5
oracledatabase.domain.local    /opt/nfsshare/u03    1.01    20      1       5
oracledatabase.domain.local    /opt/nfsshare/u04    1.01    20      1       5
oracledatabase.domain.local    /opt/nfsshare/u05    1.01    20      1       5
oracledatabase.domain.local    /opt/nfsshare/u07    1.01    20      1       5
oracledatabase.domain.local    /opt/nfsshare/u08    1.01    20      1       5
oracledatabase.domain.local    /boot                        20              5
oracledatabase.domain.local    /opt/nfsshare/u06            20              5
oracledatabase.domain.local    /opt/nfsshare/u13            20              5
oracledatabase.domain.local    /dev                         20              5
oracledatabase.domain.local    /opt/nfsshare/u11            20              5
oracledatabase.domain.local    /opt/nfsshare/u12            20              5
oracledatabase.domain.local    /                            20              5
oracledatabase.domain.local    /opt/nfsshare/u10            20              5
oracledatabase.domain.local    /opt/nfsshare/u09            20              5

16 rows selected.

https://docs.oracle.com/cd/B28359_01/server.111/b28286/functions023.htm#SQLRF00617 COALESCE возвращает первое ненулевое выражение в списке выражений . Вы должны указать как минимум два выражения. Если все вхождения expr имеют значение null, то функция возвращает null.

1 Ответ

0 голосов
/ 30 октября 2018

Этого можно добиться, используя оригинальные таблицы, объединения и отсутствие CTE

Например, если предположить, что ваши таблицы - это МОНТАЖНЫЕ И ПОРОГИ:

SELECT A.HOSTNAME, A.MOUNTPOINT, 
COALESCE(T1.WARNING_PCT,T2.WARNING_PCT) WARNING_PCT, 
COALESCE(T1.CRITICAL_PCT, T2.CRITICAL_PCT) CRITICAL_PCT
FROM MOUNTPOINTS A
LEFT OUTER JOIN THRESHOLDS T1 ON A.MOUNTPOINT = T1.MOUNTPOINT --match
JOIN THRESHOLDS T2 ON COALESCE(TRIM(T2.MOUNTPOINT),'DEFAULT') = 'DEFAULT'

Обратите внимание, что я использовал TRIM здесь, чтобы изменить значение по умолчанию, если у него есть пробел ('') на пустую строку, которая в оракуле считается NULL.

SQL Fiddle

...