Преобразование запроса TSQL в Oracle не работает

#sql #oracle #oracle11g #database-migration

#sql #Oracle #oracle11g #база данных-миграция

Вопрос:

У меня есть запрос tsql в SQL Server, который работает нормально. Но когда я использую его внутри задачи execute sql в ssis для запуска с Oracle DB. Я получаю ошибки для «функция не разрешена в группе». Я знаю, что группировка Oracle отличается, но я недостаточно хорошо разбираюсь в этом, чтобы знать достаточно.

Как мне преобразовать этот запрос tsql в oracle — sql:

 SELECT 
    TBL_A.EID AS MYID
    , TBL_A.ID
    , TBL_B.LOGIN AS LOGID  
    , TO_DATE(TBL_B.CM, 'MM/DD/YYYY') as MD 
    , sum(TBL_B.CS) as TTS
    , sum(TBL_B.COTS) as HTS
    , sum(TBL_B.CWS) as WTS
    , sum(TBL_B.CL) as NTS
FROM 
    SRVR1.TBL1 TBL_A JOIN
    SRVR2.TBL2 TBL_B
    ON TBL_A.ID = TBL_B.LOGIN

GROUP BY
    TBL_A.EID
    ,TBL_A.ID
    ,TBL_B.LOGIN
    ,TO_DATE(TBL_B.CM, 'MM/DD/YYYY') as MD  

ORDER BY TBL_B.LOGIN,
    TBL_B.CM    ;
 

Комментарии:

1. group by sum(..) не имеет никакого смысла вообще. Ни в Oracle, ни в SQL Server. Что именно вы DATEFROMPARTS делаете? И year() в Oracle нет никакой функции. Вы сами это написали? Каково намерение rownum < 5 «там»? Это сработает не так, как вы думаете. И, пожалуйста, добавьте точное сообщение об ошибке к вашему вопросу.

2. Независимо от того, какую СУБД вы используете, вы должны использовать объединения в стиле ANSI-92. Прошло более 25 лет с момента его появления. sqlblog.com/blogs/aaron_bertrand/archive/2009/10/08 /…

3. Нет никаких шансов, что запрос работает так, как опубликовано в sql server. У вас есть агрегированные данные в group by, и у вас также есть столбцы с псевдонимами в group by. Рассматривали ли вы возможность преобразования в date вместо всех этих функций, чтобы превратить datetime в дату?

4. Также удалите псевдоним столбца ( as MD ) из GROUP BY предложения. group by Предложение не должно быть cut-n-paste select предложения!

5. Функции datefromparts можно упростить до этого. преобразовать(дата, getdate())

Ответ №1:

Я бы предложил начать с такого запроса:

 SELECT TBL_A.EID AS MYID, TBL_A.ID AS LOGID  
       DATEFROMPARTS(year(TBL_B.CM), month(TBL_B.CM), day(TBL_B.CM)) as MD 
       sum(TBL_B.CS) as TTS,
       sum(TBL_B.COTS) as HTS,
       sum(TBL_B.CWS) as WTS,
       sum(TBL_B.CL) as NUM
FROM SRVR1.TBL1 TBL_A JOIN
     SRVR2.TBL2 TBL_B
     ON TBL_A.ID = TBL_B.LOGIN
WHERE rownum < 5
GROUP BY TBL_A.EID, TBL_A.ID, TBL_B.LOGIN,
          DATEFROMPARTS(year(TBL_B.CM),month(TBL_B.CM),day(TBL_B.CM)) 
ORDER BY TBL_B.LOGIN, TBL_B.CM ;
 

Примечания:

  • Никогда не используйте запятые в FROM предложении. Всегда используйте явный JOIN синтаксис.
  • Не ставьте функции агрегирования, как SUM() в GROUP BY .
  • Почему id и login в SELECT ? JOIN Условие указывает, что они одинаковы.

Кроме того:

  • datefromparts() это функция только для SQL Server
  • year() , month() , и day() доступны только для SQL Server
  • rownum только для Oracle
  • И rownum перед GROUP BY тем, как просто возвращает 5 произвольных строк, которые затем агрегируются.

Я не уверен, каким на самом деле должен быть ваш запрос. Это выглядело бы иначе в SQL Server по сравнению с Oracle.

Комментарии:

1. Я бы, по крайней мере, сделал оговорку, что where будет применен перед group by и order by , поэтому это не вернет «5 лучших совокупных строк», а займет 5 произвольных строк, сгруппирует их и упорядочит результаты. Это кажется маловероятным, чтобы быть правильным.

2. Я просто добавил rownum в качестве замены top n в sql server. Это наполовину испеченный запрос, который я пытался преобразовать. Как мне создать версию datefromparts для oracle?

3. @DamonMatt … Что-то использует. to_date()

4. Внес изменения для oracle и изменил исходное сообщение — по-прежнему появляется ошибка «команда sql не завершена должным образом».

5. @Gordon Linoff — Мне нужны первые два столбца в моем наборе данных.