2015-09-29 3 views
4

В настоящее время у меня есть оператор CASE, который проверяет, завершены ли определенные задачи или нет, а затем возвращает дату следующей задачи. Поскольку задачи упорядочены, каждый оператор WHEN становится длиннее, проверяя каждую из предыдущих задач, чтобы проверить, завершены ли они. По какой-то причине после первого WHEN-заявления он пропускает прямо к ELSE (он должен соответствовать условиям второго или третьего КОГДА).SQL CASE, проверяющий два условия из того же столбца

CASE 
    WHEN T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS != 2 THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TECH PEP MEETING DATE' AND PRISMILESTONE = 1) 
    WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2) AND (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2) THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'BRU MEETING DATE' AND PRISMILESTONE = 1) 
    WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2) AND (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS = 2) AND (T.PRNAME = 'TSC MEETING DATE' AND T.PRSTATUS != 2) THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TSC MEETING DATE' AND PRISMILESTONE = 1) 
    ELSE (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'END OF EVALUATE PHASE' AND PRISMILESTONE = 1) 
END 

Есть ли какой-либо конкретный способ, с помощью которого вам необходимо обращаться к этим типам нескольких условий КОГДА?

EDIT: Итак, после некоторых отзывов от вас, ребята, я согласен с тем, что вам нужно всего лишь оценить одну задачу за КОГДА, потому что оператор CASE должен выйти, как только он найдет свой первый TRUE-оператор. Тем не менее, обновив его:

CASE 
    WHEN UPPER(T.PRNAME) = 'EVALUATE TECH PEP MEETING DATE' AND T.PRSTATUS != 2 THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TECH PEP MEETING DATE' AND PRISMILESTONE = 1 AND ROWNUM = 1) 
    WHEN UPPER(T.PRNAME) = 'EVALUATE BRU MEETING DATE' AND T.PRSTATUS != 2 THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'BRU MEETING DATE' AND PRISMILESTONE = 1 AND ROWNUM = 1) 
    WHEN UPPER(T.PRNAME) = 'EVALUATE TSC MEETING DATE' AND T.PRSTATUS != 2 THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TSC MEETING DATE' AND PRISMILESTONE = 1 AND ROWNUM = 1) 
    ELSE (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'END OF EVALUATE PHASE' AND PRISMILESTONE = 1) 
END 

Я теперь получаю:

ORA-01427: single-row subquery returns more than one row 

Не знаю, почему это так, особенно надев ROWNUM = 1 на конце, чтобы обеспечить только один результат возвращается.

При выполнении ТО само по себе:

SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') 
FROM PRTASK T 
WHERE T.PRPROJECTID = INV_INVESTMENTS.ID 
AND Upper(T.PRNAME) = 'TECH PEP MEETING DATE' 
AND PRISMILESTONE = 1 
AND ROWNUM = 1 

Я получаю один результат. Если я прав, считая, что оператор CASE выйдет, как только он найдет свой первый TRUE-оператор, почему это находит несколько строк?

EDIT 2: Хорошо, поэтому я еще немного поиграл с этим (потому что я до сих пор не могу найти логический ответ, и я немного продвинулся вперед. Теперь я изменил способ структурирования запроса следующий:.

SELECT DISTINCT To_Char(T.PRFINISH, 'DD/MM/YY'), 
       T.PRNAME 
FROM PRTASK T 
     LEFT OUTER JOIN INV_INVESTMENTS ON T.PRPROJECTID = INV_INVESTMENTS.ID 
WHERE T.PRNAME = CASE 
        WHEN (T.PRNAME = 'Concept Tech PEP Meeting Date' AND T.PRSTATUS != 2) THEN 'Concept Tech PEP Meeting Date' 
        WHEN (T.PRNAME = 'Concept BRU Meeting Date' AND T.PRSTATUS != 2) THEN 'Concept BRU Meeting Date' 
        WHEN (T.PRNAME = 'End of Concept Phase' AND T.PRSTATUS != 2) THEN 'End of Concept Phase'                             
        WHEN (T.PRNAME = 'Evaluate Tech PEP Meeting Date' AND T.PRSTATUS != 2) THEN 'Evaluate Tech PEP Meeting Date' 
        WHEN (T.PRNAME = 'Evaluate BRU Meeting Date' AND T.PRSTATUS != 2) THEN 'Evaluate BRU Meeting Date' 
        WHEN (T.PRNAME = 'Evaluate TSC Meeting Date' AND T.PRSTATUS != 2) THEN 'Evaluate TSC Meeting Date' 
        WHEN (T.PRNAME = 'End of Evaluate Phase' AND T.PRSTATUS != 2) THEN 'End of Evaluate Phase'      
        WHEN (T.PRNAME = 'End of Analyse Phase' AND T.PRSTATUS != 2) THEN 'End of Analyse Phase' 
        WHEN (T.PRNAME = 'End of Design Phase' AND T.PRSTATUS != 2) THEN 'End of Design Phase' 
        WHEN (T.PRNAME = 'End of Build Phase' AND T.PRSTATUS != 2) THEN 'End of Build Phase' 
        WHEN (T.PRNAME = 'End of Test Phase' AND T.PRSTATUS != 2) THEN 'End of Test Phase' 
        WHEN (T.PRNAME = 'In Service' AND T.PRSTATUS != 2) THEN 'In Service'      
        WHEN (T.PRNAME = 'End of Implement Phase' AND T.PRSTATUS != 2) THEN 'End of Implement Phase' 
        WHEN (T.PRNAME = 'End of Closure Phase' AND T.PRSTATUS != 2) THEN 'End of Closure Phase' 
        ELSE 'In Service' 
        END 
    AND INV_INVESTMENTS.CODE = '007058' 

Теперь, однако, я получаю множественный КОГДА заявления возвращения значения Может кто-нибудь подтвердить, действительно ли или нет заявление СЛУЧАЯ возвращает только первый ИСТИНУ значения

+0

Вы должны использовать или инструкцию вместо И во втором и третьем случаях. например (T.PRNAME = «ТЕХНИЧЕСКАЯ ЗАСЕДАНИЯ PEP» и T.PRSTATUS = 2) AND (T.PRNAME = 'BRU MEETING DATE' и T.PRSTATUS! = 2) должны быть написаны следующим образом (T.PRNAME = 'TECH PEP MEETING DATE' И T.PRSTATUS = 2) ИЛИ (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS! = 2) –

+0

@Matthew основывается на вашей ошибке, проблема заключается в вашем запросе 'SELECT', он возвращает более 1 строки/записи, попробуйте проверить инструкцию' SELECT' speciailly на 'WHERE' состоянии если почему он возвращает более 1 строки. – Japongskie

+0

@Matthew вы попробовали 3-й 'WHEN', там также есть инструкция SELECT TO_CHAR (MAX (T.PRFINISH), 'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper (T.PRNAME) = 'TSC MEETING DATE' И PRISMILESTONE = 1 И ROWNUM = 1', любезно попробуйте, если также вернет 1 запись. – Japongskie

ответ

4

T.PRNAME? = 'ТЕХНИЧЕСКАЯ ЗАПОВЕДНИКА PEP' И T.PRNAME = 'BRU ДЕНЬ СОВЕЩАНИЯ?? Я думаю, у нас здесь есть перекрывающиеся условия.

Мое высокое предположение заключается в том, что у вас есть 1 стол со многими задачами со статусом рядом, тогда я думаю, что здесь должно произойти что-то, как показано ниже.

Во-первых, ваша таблица задач, я создал что-то свое.

CREATE TABLE #testtask 
    (
    PRID INT 
    , PRNAME varchar(50) 
    , PRSTATUS INT 
    , PREREQ INT 
) 

    INSERT INTO #testtask VALUES 
    (1,'TECH PEP MEETING DATE',1,0), 
    (2,'BRU MEETING DATE',1,1), 
    (3,'TSC MEETING DATE',1,2) 

Must может быть что-то вроде этого

Затем я создал левое соединение по своей таблице, связанной с его предварительным условием задачи.

SELECT 
    t1.PRNAME AS [Job] 
    , t1.PRSTATUS AS [JobStatus] 
    , t2.PRNAME AS [PreReqJob] 
    , t2.PRSTATUS AS [PreReqStatus] 
    INTO #taskList 
    FROM #testtask t1 
    LEFT JOIN #testtask t2 
    ON 
    t1.PREREQ = t2.PRID 

и с этим следующий результат.

enter image description here

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

SELECT 
     CASE 
     WHEN tl.[Job] = 'TECH PEP MEETING DATE' AND tl.[JobStatus] != 2 
      THEN 
       -- do your max select here for 'Tech pep' 
     WHEN tl.[Job] = 'BRU MEETING DATE' AND tl.[JobStatus] != 2 AND tl.[PreReqStatus] = 2 
      THEN 
       -- do your max select here for 'Bru meet' 
     WHEN tl.[Job] = 'TSC MEETING DATE' AND tl.[JobStatus] != 2 AND tl.[PreReqStatus] = 2 
      THEN 
       -- do your max select here for 'Tsc meet' 
     ELSE 
      -- do your default max date 
    END AS [Date] 
    FROM #taskList AS tl 

Пожалуйста, получите концепцию самостоятельно, так как у меня нет ваших фактических таблиц. У вас будет большая ошибка, если вы скопируете все это. Надеюсь, что это помогает :)

2

Во-первых, исправить случай заявление для того, что lad2025 указывает, но не с помощью каких-либо OR и упрощена

CASE 
    WHEN T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS != 2 THEN ... 
    WHEN T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2 THEN ... 
    WHEN T.PRNAME = 'TSC MEETING DATE' AND T.PRSTATUS != 2 THEN ... 
    ELSE ... 
END 

Тогда еще больше упростить, используя случай, чтобы использовать один и тот же запрос

(
    SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') 
    FROM PRTASK T 
    WHERE T.PRPROJECTID = INV_INVESTMENTS.ID 
     AND PRISMILESTONE = 1 
     AND Upper(T.PRNAME) = 
      CASE 
       WHEN T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS != 2 THEN 'TECH PEP MEETING DATE' 
       WHEN T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2 THEN 'BRU MEETING DATE' 
       WHEN T.PRNAME = 'TSC MEETING DATE' AND T.PRSTATUS != 2 THEN 'TSC MEETING DATE' 
       ELSE 'END OF EVALUATE PHASE' 
      END 
) 
+0

Предположим, я должен был подумать о том, что CASE выйдет, как только он найдет первое истинное значение (я считаю, это так), и в этом случае вы правы. По-моему, это сложнее. –

+0

@MatthewPaxman Дублирование вашего подзапроса в операторе 'CASE' затрудняет обнаружение ошибки с помощью проверки глазного шара, и в результате вы теряете какое-то условие (ROWNUM = 1) в последнем утверждении. – Eric

2

Попытка ответить на вопрос ROWNUM = 1, вы уверены, что работаете в одной из ветвей THEN? У вас нет ROWNUM = 1, указанного в ветке ELSE. Помогает ли также добавить ROWNUM = 1?

1

Ваше состояние CASE WHEN конфликтует друг с другом, у вас есть проблема с использованием AND. Ваш второй и третий WHEN всегда будут возвращать FALSE, почему? посмотреть на этой линии ..

WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2) 
    AND (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2) 
    THEN... 

Это один T.PRNAME = 'TECH PEP MEETING DATE находится в противоречии с условием AND рядом с ним AND (T.PRNAME = 'BRU MEETING DATE', что условие никогда не будет возвращать TRUE же на ваш третий WHEN

Использование AND только возвращает истину, если два условия между AND это правда.

Читая ваши коды, кажется, ваш AND в каждом WHEN вашего кода необходимо заменить OR исправить/удалить конфликтующие условия в столбце T.PRNAME

Ниже кода ваши, я модифицирована его замены AND по OR, чтобы исправить ваше состояние.

CASE 
    WHEN T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS != 2 
     THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TECH PEP MEETING DATE' AND PRISMILESTONE = 1) 
    WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2) OR (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS != 2) 
     THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'BRU MEETING DATE' AND PRISMILESTONE = 1) 
    WHEN (T.PRNAME = 'TECH PEP MEETING DATE' AND T.PRSTATUS = 2) OR (T.PRNAME = 'BRU MEETING DATE' AND T.PRSTATUS = 2) AND (T.PRNAME = 'TSC MEETING DATE' AND T.PRSTATUS != 2) 
     THEN (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'TSC MEETING DATE' AND PRISMILESTONE = 1) 
    ELSE (SELECT TO_CHAR(MAX(T.PRFINISH),'DD/MM/YY') FROM PRTASK T WHERE T.PRPROJECTID = INV_INVESTMENTS.ID AND Upper(T.PRNAME) = 'END OF EVALUATE PHASE' AND PRISMILESTONE = 1) 
END 

Надеюсь, это поможет.

+0

Привет, Japz, к сожалению, использование OR не помогло мне в этом CASE, но, поняв, что CASE выйдет, когда найдет условие TRUE, я все равно понял, что это не имеет значения. Я редактировал AND часть из кода в нижней части моего сообщения. Возвращение более одной ошибки результата - моя текущая проблема. Все еще пытаюсь выяснить, почему это так. –

+0

@MatthewPaxman i see, ok позволяет перейти к вашей текущей проблеме сейчас, вы сказали, что вы сами запускаете 'SELECT'? , и он возвращает только 1 строку? , вы попробовали другой оператор SELECT, если он также возвращает только 1 строку? – Japongskie

+0

Да, все они возвращают одну строку. Интересно, что если я изменю «UPPER (T.PRNAME)» на просто «T.PRNAME», запрос не вернет ошибку, но он всегда даст мне результат ELSE, несмотря на то, что я вижу, что одно из предложений WHEN являются истинными. Точно так же, если я изменю «ТЕХНИЧЕСКИЙ СОБЫТИЙ PEP» на 'Tech PEP Meeting Date', я снова получу ошибку. Не уверен, почему чувствительность к регистру нарушает это, поскольку каждый из этих PRNAME уникален. –

2

ммм,

я пытался sqlfiddle ваш вопрос, но есть к гораздо неизвестным таблицам, используемых. Чтобы получить лучшую помощь, попробуйте создать некоторые sqlfiddle, которые могут использовать ваши помощники.

После некоторых исследований мне кажется, что оракул на самом деле не проверяет, если ваш запрос возвращает только одну строку. он проверяет, может ли ваш синтаксис разрешить только одну строку. Я не уверен в этом.

Попробуйте использовать max (x) вокруг всех ваших особых полей подзапроса-возврата и взгляните, если оракул примет это. Если вы действительно получаете только одну строку, max() не изменяет ваше значение, поэтому используйте его.

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