Возвращение table_name и partition_name, количество которых имеют значение 0

голоса
1

Я пытаюсь писать запрос, вернуть table_name и partition_name которого граф этого раздела имеет значение 0.

У меня есть ниже запрос, который возвращает SELECT COUNT () таблиц и его разделов:

SELECT 'SELECT COUNT(*) FROM ' || TABLE_NAME || ' PARTITION (' || PARTITION_NAME || ');'
FROM user_tab_partitions
ORDER BY table_name;

Вот некоторые из SELECT, что возвращение:

SELECT COUNT(*) FROM A5109713 PARTITION (PT5109713_201210);
SELECT COUNT(*) FROM A5109713 PARTITION (PT5109713_201104);
SELECT COUNT(*) FROM A5109713 PARTITION (PT5109713_201301);

Последний из них это только то, что возвращаемые данные:

COUNT(*) |
2430276  |

Что мне нужно, это запрос, который возвращает table_name и partition_name тех, кто не имеет никаких данных. Что-то вроде этого:

TABLE_NAME | PARTITION_NAME
A5109713   | PT5109713_201210
A5109713   | PT5109713_201104
Задан 13/02/2020 в 23:52
источник пользователем
На других языках...                            


2 ответов

голоса
0

Этот метод с использованием динамического SQL тяжело реализовать, и медленно, чтобы выполнить (так как вам нужно вручную подсчет строк в каждой секции). Кроме того, теперь вы оказываетесь в потребности некоторой дополнительной логики, то потребуется больше PL / SQL кода.

Вид системы user_tab_partitionsимеет столбец , num_rowsкоторый документированный , как : Количество строк в разделе . Достоверность содержащейся в нем информации зависит от свежести вашей статистики.

Таким образом, если ваша статистика в актуальном состоянии, то вы можете получить информацию, которую вы ищете прямо с точки зрения:

select table_name, partition_name
from user_tab_partitions
where num_rows = 0
order by table_name, partition_name
Ответил 14/02/2020 в 00:11
источник пользователем

голоса
0

Я бы процедура, как это:

DECLARE
    r INTEGER;
    cur sys_refcursor;
BEGIN
    FOR aPart IN (SELECT TABLE_NAME, PARTITION_NAME FROM USER_TAB_PARTITIONS ORDER BY TABLE_NAME, PARTITION_POSITION) LOOP
        OPEN cur FOR 'SELECT ROWNUM FROM '||aPart.TABLE_NAME||' PARTITION ('||aPart.PARTITION_NAME||') WHERE ROWNUM <= 1';
        FETCH cur INTO r;
        IF cur%NOTFOUND THEN
            DBMS_OUTPUT.PUT_LINE(aPart.TABLE_NAME||CHR(9)||aPart.PARTITION_NAME);
        end if;
        close cur;
    END LOOP;
END;

Я бы не стал полагаться на NUM_ROWSна мнение , USER_TAB_PARTITIONSпотому что достоверность содержащейся в нем информации зависит от свежести вашей статистики.

Я использую SELECT ROWNUM FROM ... WHERE ROWNUM <= 1;вместо COUNT(*)по причине производительности. На самом деле вы не заинтересованы в общем количестве строк, вы так же , как знать , являются ли они больше 0.

В худшем случае COUNT(*)работает FULL-сканирование таблицы , которая намного медленнее , чем чтение только первая запись.

Ответил 14/02/2020 в 13:35
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more