2016-07-22 3 views
1

я сделать этот запрос в базе данных Oracle 11gИмея пункт не работает

 SELECT DISTINCT JOC_FIN_CLTH_DFCT_LOT.LOT_NO, 
        I.ISSUE_DATE, 
        R.PROC_DESC, 
        R.RECV_DATE, 
        M.DFCT_DATE, 
        JOC_FIN_CLTH_DFCT_LOT.FCD_MAIN_ID 
    FROM JOC_FIN_CLTH_DFCT_LOT, 
      JOC_FIN_CLTH_DFCT_MAIN M, 
      JOC_DAILY_FABRC_RECV_FOLD R, 
      JOC_LOT_ISSUE_REG I 
    WHERE  M.FCD_MAIN_ID = JOC_FIN_CLTH_DFCT_LOT.FCD_MAIN_ID 
      AND R.LOT_NO = JOC_FIN_CLTH_DFCT_LOT.LOT_NO 
      AND I.LOT_NO = R.LOT_NO 
      AND I.LOT_YEAR = R.LOT_YEAR 
      AND JOC_FIN_CLTH_DFCT_LOT.LOT_YEAR = R.LOT_YEAR 
      AND JOC_FIN_CLTH_DFCT_LOT.LOT_YEAR = '1213' 
      AND JOC_FIN_CLTH_DFCT_LOT.FCDL_ID IN 
        ( SELECT MIN (DFCT_LOT.FCDL_ID) 
    FROM JOC_FIN_CLTH_DFCT_LOT DFCT_LOT, JOC_FIN_CLTH_DFCT_MAIN DFT_MAIN 
    WHERE DFCT_LOT.FCD_MAIN_ID IN (DFT_MAIN.FCD_MAIN_ID) 
GROUP BY DFCT_LOT.FCD_MAIN_ID) 
ORDER BY JOC_FIN_CLTH_DFCT_LOT.FCD_MAIN_ID 

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

SELECT DISTINCT DFCT_LOT.LOT_NO, 
        I.ISSUE_DATE, 
        R.PROC_DESC, 
        R.RECV_DATE, 
        M.DFCT_DATE, 
        DFCT_LOT.FCD_MAIN_ID 
    FROM JOC_FIN_CLTH_DFCT_LOT DFCT_LOT, 
      JOC_FIN_CLTH_DFCT_MAIN M, 
      JOC_DAILY_FABRC_RECV_FOLD R, 
      JOC_LOT_ISSUE_REG I, 
      JOC_FIN_CLTH_DFCT_MAIN DFT_MAIN 
    WHERE  M.FCD_MAIN_ID = DFCT_LOT.FCD_MAIN_ID 
      AND R.LOT_NO = DFCT_LOT.LOT_NO 
      AND I.LOT_NO = R.LOT_NO 
      AND I.LOT_YEAR = R.LOT_YEAR 
      AND DFCT_LOT.LOT_YEAR = R.LOT_YEAR 
      AND DFCT_LOT.LOT_YEAR = '1213' 
      AND DFCT_LOT.FCD_MAIN_ID IN (DFT_MAIN.FCD_MAIN_ID) 

GROUP BY DFCT_LOT.FCDL_ID, 
      DFCT_LOT.FCD_MAIN_ID, 
      DFCT_LOT.LOT_NO, 
      I.ISSUE_DATE, 
      R.PROC_DESC, 
      R.RECV_DATE, 
      M.DFCT_DATE, 
      DFCT_LOT.FCD_MAIN_ID 
HAVING DFCT_LOT.FCDL_ID in MIN (DFCT_LOT.FCDL_ID) 
ORDER BY DFCT_LOT.FCD_MAIN_ID 

это упрощенный форму выше запроса, но число строк увеличивается no.of rows = 5578, но я знаю фактический номер. рядов = 5100 имеющий пункт не работает здесь любезно заглянуть в мой запрос и направлять мне

+0

'min' возвращает одно значение, и вы используете' in' с ним? –

+0

так что я использую с ним ??? – usman

+0

Почему не просто '='? –

ответ

1

В вашем втором запросе вы присоединяетесь таблицу JOC_FIN_CLTH_DFCT_MAIN во второй раз, один раз как M и один раз как DFCT_LOT. В списке второго запроса SELECT вы берете первый столбец от M, а последний - от DFCT_LOT.

Но в первом запросе они оба из той же таблицы M. Когда у вас есть более одной записи в JOC_FIN_CLTH_DFCT_MAIN для того же FCD_MAIN_ID, это приведет к большему количеству комбинаций во втором запросе, и это объясняет, почему у вас больше результатов.

Но есть еще несколько отличий. Во втором запросе вы группируете гораздо больше столбцов, чем в первом. Более того, MIN (DFCT_LOT.FCDL_ID) на самом деле не имеет смысла во втором запросе, поскольку он уже сгруппирован, поэтому он точно такой же, как и DFCT_LOT.FCDL_ID. Как следствие, предложение HAVING - это просто тавтология, и вы можете просто оставить ее и получить те же результаты.

Если вы уверены, что первый запрос дает результаты, которые вы хотите, то я бы предложил другой способ достижения возможной оптимизации этого:

SELECT  DISTINCT 
      L.LOT_NO, 
      I.ISSUE_DATE, 
      R.PROC_DESC, 
      R.RECV_DATE, 
      L.DFCT_DATE, 
      L.FCD_MAIN_ID, 
FROM  (SELECT  L.FCD_MAIN_ID, 
         L.LOT_NO, 
         L.LOT_YEAR, 
         M.DFCT_DATE, 
         ROW_NUMBER() OVER (PARTITION BY L.FCD_MAIN_ID 
              ORDER BY L.FCDL_ID) AS RN 
      FROM  JOC_FIN_CLTH_DFCT_LOT L, 
      INNER JOIN JOC_FIN_CLTH_DFCT_MAIN M 
        ON M.FCD_MAIN_ID = L.FCD_MAIN_ID 
      ) L 
INNER JOIN JOC_DAILY_FABRC_RECV_FOLD R 
     ON R.LOT_NO = L.LOT_NO 
     AND R.LOT_YEAR = L.LOT_YEAR 
INNER JOIN JOC_LOT_ISSUE_REG I 
     ON I.LOT_NO = R.LOT_NO 
     AND I.LOT_YEAR = R.LOT_YEAR 
WHERE  L.LOT_YEAR = '1213' 
     AND L.RN = 1 
ORDER BY L.FCD_MAIN_ID 

Обратите внимание, что я использовал синтаксис ANSI/ISO для которые я бы настоятельно советовал вам делать. Определение условий соединения в предложении WHERE - это что-то из восьмидесятых; не делай этого. Запросы становятся более читабельными, когда вы используете синтаксис ANSI/ISO.

Предлагаемый запрос выбирает все столбцы, которые необходимы как из JOC_FIN_CLTH_DFCT_LOT, так и JOC_FIN_CLTH_DFCT_MAIN в подзапросе, так что вам не нужно включать эти таблицы снова.

Основной трюк заключается в использовании оконной функции ROW_NUMBER, которая дает порядковый номер в соответствии с пунктом PARTITION. Внешний запрос затем фильтрует только те записи, которые получили номер 1, которые являются записями, где значение FCD_MAIN_ID минимально для заданного FCDL_ID.

Смежные вопросы