Объединяя UNION, count(*) и rowid в SQL, он же определяет блоки, используемые двумя таблицами

У меня есть 2 таблицы МАМА и РЕБЕНОК. Я хочу определить, сколько блоков они используют вместе. Код, который я обычно использую, чтобы определить это только для одной таблицы

select count(count(dbms_rowid.rowid_block_number(rowid))) 
from MOTHER group by dbms_rowid.rowid_block_number(rowid);

но так как мне нужны обе таблицы и они могут использовать одни и те же блоки, я попытался поэкспериментировать. Итак, я прочитал, что UNION может решить эту проблему, но у меня проблемы с его использованием в соответствии с учебниками

select tem.dbms_rowid.rowid_block_number(rowid), count(*) from
(select dbms_rowid.rowid_block_number(rowid) from MOTHER 
union
select dbms_rowid.rowid_block_number(rowid) from CHILD ) AS tem
group by dbms_rowid.rowid_block_number(rowid);

это не работает и показывает ошибку на AS tem часть. Это говорит синтаксическая ошибка. сообщение:

ORA-00933: Команда SQL не была правильно завершена 00933. 00000 - "Команда SQL не была правильно завершена" * Причина:
* Действие: Ошибка в строке: 18 Колонка: 58

1 ответ

Решение

В запросе есть несколько ошибок.

Первым, который вызывает немедленную ошибку, является ключевое слово AS, В Oracle (отличается от других продуктов баз данных, от того, что я понимаю), ключевое слово AS необязательно для псевдонимов столбцов и запрещено для псевдонимов таблиц / подзапросов. Удалить слово AS перед псевдонимом tem и эта ошибка исправлена.

Затем во внешнем выборе вы все еще хотите выбрать из dbms_rowid - но это невозможно, вы уже дали псевдоним псевдониму, поэтому вы можете выбирать только из него, а не из таблиц, на которые есть ссылки в двух ветвях union,

Вот один из способов исправить это:

select   rowid_block_number, count(*) as cnt    -- DON'T USE THIS QUERY! (SEE BELOW)
from     
         ( 
           select dbms_rowid.rowid_block_number(rowid) as rowid_block_number from MOTHER 
           union
           select dbms_rowid.rowid_block_number(rowid) from CHILD
         )
group by rowid_block_number
;

Обратите внимание, что я покончил с псевдонимом для подзапроса - он не нужен. Кроме того, я дал псевдоним столбцу в результате применения rowid_block_number(rowid) - Вы не можете назвать это как во внешнем запросе.

Теперь это синтаксически правильно, но логика не существует. Что касается вашего первого счета, я понятия не имею, почему вы группируете и выбираете счет дважды. Вы должны просто

select count(distinct dbms_rowid.rowid_block_number(rowid)) as block_count
from   MOTHER;

и если вы должны сделать это для двух разных таблиц:

select count(distinct rowid_block_number) as block_count
from   
       ( 
         select dbms_rowid.rowid_block_number(rowid) as rowid_block_number from MOTHER
         union all
         select dbms_rowid.rowid_block_number(rowid) from CHILD
       )
;

или, если вы будете использовать union вместо union all, что уже устранит дубликаты, так что просто select count(rowid_block_number) из подзапроса. (То есть: вам нужна какая-то форма "отличная", но она нужна только один раз. Либо подсчитайте отличную во внешнем запросе, либо используйте union как вы делали, а не union all, в подзапросе, но тогда вам не нужно "отличить" во внешнем запросе.)

Другие вопросы по тегам