#sql #oracle #subquery
#sql #Oracle #подзапрос
Вопрос:
Я пытаюсь получить общее количество транзакций из таблицы между заданной датой в базе данных oracle.Я написал подзапрос для группировки уникальных транзакций, и когда я пытаюсь суммировать столбцы в подзапросе, я получаю сообщение об ошибке ORA-00904: ColumnName: недопустимый идентификатор. Я новичок в oracle, но это же работало для меня в sql server.
Вот мой запрос.
select sum(Tots),sum(CRIR),sum(RT),sum(Succes) from(
select ds.LOAN_ID,ds.CUST_ID,TO_CHAR(ds.SENT_DT_TIME, 'YYYY-MM-DD') "Dates", count(*) "Tots",
SUM(DECODE (ds.STATUS, 'CR', 1,'IR',1,0)) "CRIR",
SUM(DECODE (ds.STATUS, 'R', 1,'T',1,0)) "RT",
SUM(DECODE (ds.STATUS, 'S', 1, 0)) "Succes"
FROM DATA_STRING ds
WHERE TRUNC(ds.SENT_DT_TIME) BETWEEN to_date('2016-10-04','yyyy-mm-dd') and to_date('2016-10-07','yyyy-mm-dd')
Group by ds.LOAN_ID,ds.CUST_ID,TO_CHAR(ds.SENT_DT_TIME, 'YYYY-MM-DD')
);
Комментарии:
1. Каково полное сообщение об ошибке? Это должно указать вам на строку и позицию идентификатора-нарушителя, это помогает? (Поделитесь этой информацией здесь, если вам нужна дополнительная помощь.)
Ответ №1:
Ваш запрос был бы намного проще записать как:
select count(*),
sum(case when status in ('CR', 'IR') then 1 else 0 end) as CRIR,
sum(case when status in ('R', 'T') then 1 else 0 end) as RT,
sum(case when status in ('S') then 1 else 0 end) as Succes
from data_string ds
where ds.sent_dt_time >= date '2016-10-04' and
ds.sent_dt_time < date '2016-10-08';
Примечания:
- Для того, что вы хотите сделать, не требуется два уровня агрегирования.
- Используйте
case
вместоdecode()
, потомуcase
что это стандартный SQL. Также проще включить такую логику, какin
. - Oracle поддерживает
date
ключевое слово, за которым может следовать стандартная дата. - Почти точно такой же запрос работает в SQL Server (за вычетом
date
ключевого слова).
Комментарии:
1. Я хочу выполнить группировку, чтобы сгруппировать все уникальные транзакции за день
2. @Raju . , , Можно ответить только на вопрос, который вы задаете. Двойная агрегация не требуется. Если у вас есть другой вопрос, задайте его как другой вопрос. Если вы измените это, это может сделать недействительным этот ответ и, следовательно, привлечь отрицательные голоса.
3. почему это работает на SQL server, а не на Oracle ? !! .. Какие-либо ограничения в Oracle для двухуровневых агрегаций?
4. @Raju . , , я не говорил, что это не будет работать с двумя уровнями агрегации, просто эта версия проще и более переносима.
5. Если это так, то почему он выдавал ошибку для моего запроса. Я сделал что-то не так?
Ответ №2:
Только для вашей ошибки ORA-00904: ColumnName : invalid identifier
Если вы используете псевдонимы в кавычках для столбцов «Tots», «CRIR», «RT», «Succes» в подзапросе, то вам нужно использовать те же псевдонимы в кавычках в основном запросе.
Псевдонимы, заключенные в кавычки, чувствительны к регистру. Но псевдонимы без кавычек не чувствительны к регистру. Oracle интерпретирует их как прописные.
Это будет работа:
select sum("Tots"),sum("CRIR"),sum("RT"),sum("Succes") from(
select ds.LOAN_ID,ds.CUST_ID,TO_CHAR(ds.SENT_DT_TIME, 'YYYY-MM-DD') "Dates", count(*) "Tots",
SUM(DECODE (ds.STATUS, 'CR', 1,'IR',1,0)) "CRIR",
SUM(DECODE (ds.STATUS, 'R', 1,'T',1,0)) "RT",
SUM(DECODE (ds.STATUS, 'S', 1, 0)) "Succes"
FROM DATA_STRING ds
WHERE TRUNC(ds.SENT_DT_TIME) BETWEEN to_date('2016-10-04','yyyy-mm-dd') and to_date('2016-10-07','yyyy-mm-dd')
Group by ds.LOAN_ID,ds.CUST_ID,TO_CHAR(ds.SENT_DT_TIME, 'YYYY-MM-DD')
);