2015-12-05 4 views
2

Я довольно новичок в SQL. Я пытаюсь построить определенный запрос в Business Objects, вручную настроив SQL. У меня есть понимание новичком подзапросов, однако есть одна конкретная проблема, которая ускользает от меня. Я попытаюсь объяснить, используя пример кода:SQL-подзапрос: как обратиться к внешнему столбцу запроса в таблице SAME

SELECT 
TBL1.ID 
TBL1.Field1text 
TBL1.Field2date 
CASE WHEN 
    (
    TBL1.Field1text = 'ValueTwo' 
    AND 
    TBL1.Field2date >= '30/11/2014' 
    /* Arbitrary date. I actually want this to be, for example, 
     "TBL1.Field2date minus 2 months where TBL1.ID is the same, and 
     TBL1.Field1text is ValueOne" */ 
    ) 
THEN 'Match' 
ELSE 'No Match' 
END 
As CutomColumnNameToShowMatches 
WHERE 
TBL1.Field1text = 'ValueOne' 
AND 
TBL1.Field2date BETWEEN '01/01/2015' AND '31/12/2015' 

Так как вы можете видеть, я использую случай, когда положение в критериях выбора, чтобы вернуться пользовательское поле, которое показывает, есть ли совпадение или нет (поясняется ниже).

Исходная таблица содержит множество записей, в которых каждое значение поля11 связано с определенной датой (Field2date). Поле «ID» не является первичным ключом. Один и тот же идентификатор может использоваться для нескольких записей. Например, ID 52 может иметь несколько записей, все отображающие разные значения Field1text и связанные с ними Field2date. Со мной до сих пор? Хорошо.

Мой основной запрос возвращает список записей, в которых Field1text является «ValueOne». Это достаточно просто. Тем не менее, то, что я тогда хочу сделать, это определить - для каждого из этих записей:

«Take идентификационного номера поиск в таблице, и найти также имеют ли то же ID любые записи, где Field1text равняется ValueTwo, и где. Field2date этой записи ValueTwo находится в пределах 2 месяцев с момента Field2date записи ValueOne ". Если да, то верните Матч. Если нет, не возвращайте совпадение.

Все это имеет смысл? Пожалуйста, попросите меня уточнить, если необходимо.

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

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

Обратите внимание, что мы все работаем из одной таблицы. Кроме того, поскольку я работаю в Business Objects, у меня нет возможности создавать и сохранять именованный запрос, например, в MS Access. Все должно работать из одного фрагмента кода SQL.

Благодарен за любую помощь! :)

+1

Предложение 'FROM' поможет. –

+0

Знание того, что действительно представляет собой ПК, также поможет. –

+0

Также: Вы действительно имеете в виду «в течение двух месяцев» или вы имеете в виду «в течение 60 дней»? Семантика очень различна, так как 31 декабря *** *** *** в течение двух месяцев с 1 октября, хотя на 91 день позже. –

ответ

2

Назначьте различные псевдонимы в одну и ту же таблицу и присоедините их к двум псевдонимам. Используя ваш пример, я создал запрос, который показывает только строки, которые HAVE совпадают в таймфрейме. Он использует псевдонимы «A» и «B» следующим образом:

SELECT 
    a.ID, 
    a.Field1text, 
    a.Field2date 
FROM 
    TBL1 AS a 
    INNER JOIN TBL1 AS b ON 
     a.ID = b.ID 
     AND a.Field1text = b.Field1text 
     AND b.Field2date > a.Field2date 
     AND b.Field2date <= DATEADD(month, 2, a.Field2date) 

В качестве альтернативы, если вы хотите, чтобы все строки из «а» и просто показатель, если совпадение найдено в «б», то попробуйте следующее:

SELECT 
    a.ID, 
    a.Field1text, 
    a.Field2date, 
    CASE 
     WHEN 
      (
       SELECT TOP 1 
        CASE WHEN b.ID IS NULL THEN 'No Match' ELSE 'Match' END 
       FROM 
        TBL1 AS b 
       WHERE 
        a.ID = b.ID 
        AND a.Field1text = b.Field1text 
        AND b.Field2date > a.Field2date 
        AND b.Field2date <= DATEADD(month, 2, a.Field2date) 
      ) IS NULL 
     THEN 'No Match' 
     ELSE 'Match' 
    END AS [MatchSearch] 
FROM 
    TBL1 AS a 
WHERE 
    a.Field1text = 'ValueOne' 
    AND a.Field2date BETWEEN '01/01/2015' AND '12/31/2015' 

ПРИМЕЧАНИЕ: Это все равно будет отображать строки из 'b', которые соответствуют внешнему предложению WHERE. Если вы не хотите их показывать, подумайте о добавлении предложения GROUP BY.

PS: Я не смог найти раздел FROM вашего запроса, поэтому я сделал его. Кроме того, текст диапазона дат не отформатирован должным образом: '31/12/2015 '

+0

Дон - похоже, ты на что-то там. Я не знал, что можно назначить псевдонимы таблицам во время выполнения SQL (сказал, что я на нем n00b). Я попробую это завтра и сообщит, если это сработает - спасибо! –

+0

Дон, он работает! Огромное спасибо. Мне пришлось слегка изменить ваш пример, но принцип назначения псевдонима для таблицы был отличным. Btw - мой день отформатирован правильно на международном уровне. Я не американец! К сожалению, многие американские серверы переключаются между датами, поэтому я предпочитаю использовать 31-dec-2015, чтобы убедиться, что этого не произойдет :) –

+0

Awesome, Извините, что на дату смешивания мой сервер бросил ошибки. Я рад, что это сработало для вас. – Don