2010-09-03 4 views
1

Я пытаюсь написать SQL-запрос, где я соединяю две таблицы и извлекаю несколько столбцов. Как только это будет сделано, на основе двух полей (перечисление исходной таблицы, идентификатора в соответствующей исходной таблице), мне нужно получить значение, соответствующее идентификатору в исходной таблице.Вложенные запросы sql внутри футляра

Вопрос заключается в том, что я не могу объединить все исходные таблицы, и вы хотите сделать что-то вроде этого:

Select 
    X.Col1, 
    X.Col2, 
    Y.Col1, 
    Y.Col2, 
    CASE 
    WHEN Y.TableID = 4 THEN Select t4.Col1 FROM TableFour t4 WHERE t4.id = Y.FileID 
    WHEN Y.TableID = 5 THEN Select t5.Col4 FROM TableFive t5 WHERE t5.id = Y.FileID 
    END 
FROM Table X INNER JOIN Table Y ON X.ID = Y.XID 

Я могу гарантировать значение, извлекаемых из всех исходных таблиц будет одинаковым (т.е. NVARCHAR).

Вложенные SQL-запросы внутри оператора CASE, похоже, не работают, я бросаю его вам, ребята. Любые идеи с этой проблемой?

Надеюсь, я правильно объяснил вопрос. Если вы не уверены, сделайте комментарий, чтобы я мог его прояснить.

Приветствия заранее!

+0

MSSQL Server 2008 –

+0

Я не понимаю, что вы имеете в виду под «не может объединить все исходные таблицы», вы можете уточнить? –

+0

@AlexKuznetsov: Вероятно, что присоединение к этим таблицам вводит дополнительные строки, которые OP не хочет в конечном наборе результатов ... –

ответ

1

Я не понимаю, что вы имеете в виду под «не может объединить все исходные таблицы», вы можете уточнить? Я хотел бы использовать внешние соединения:

Select 
    X.Col1, 
    X.Col2, 
    Y.Col1, 
    Y.Col2, 
    COALESCE(t4.Col1 ,t5.Col4) 
    END 
FROM Table X INNER JOIN Table Y ON X.ID = Y.XID 
LEFT OUTER JOIN TableFour t4 ON t4.id = Y.FileID AND Y.TableID = 4 
LEFT OUTER JOIN TableFive t5 ON t5.id = Y.FileID AND Y.TableID = 5 
+0

Эти критерии ограничивают 'TABLE Y', а не таблицы четыре или пять ... –

+0

Нет, критерии внутри внешнего условия соединения не будут фильтровать Y. Попробуйте сами и убедитесь сами. –

0

Я бы, наверное, написать функцию для этого:

CREATE FUNCTION dbo.GetVal 
(@tblNum int, @FileID int) 
RETURNS nvarchar(255) 
AS 
BEGIN 
    Declare @return nvarchar(255); 
    if @tblNum = 4 then 
    Select @return=t4.Col1 FROM TableFour t4 WHERE t4.id = @FileID; 
    else 
    if @tblNum =5 
     Select @return=t5.Col4 FROM TableFive t5 WHERE t5.id = @FileID; 
    return @return 
END; 

Тогда ваш Select выглядит как:

Select 
    X.Col1, 
    X.Col2, 
    Y.Col1, 
    Y.Col2, 
    dbo.GetVal(Y.TableID, Y.FileID) 
FROM Table X INNER JOIN Table Y ON X.ID = Y.XID 
+0

Скалярные UDF ужасно медленны. –

+0

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

+0

Согласен. UDF - это плохой выбор. – ErikE

3

Используйте скобки, чтобы инкапсулировать ВЫБРАТЬ в выражении СЛУЧАЙ:

Select X.Col1, 
     X.Col2, 
     Y.Col1, 
     Y.Col2, 
     CASE 
     WHEN Y.TableID = 4 THEN (Select t4.Col1 FROM TableFour t4 WHERE t4.id = Y.FileID) 
     WHEN Y.TableID = 5 THEN (Select t5.Col4 FROM TableFive t5 WHERE t5.id = Y.FileID) 
     END 
    FROM Table X 
    JOIN Table Y ON X.ID = Y.XID 

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

Select X.Col1, 
      X.Col2, 
      Y.Col1, 
      Y.Col2, 
      CASE 
      WHEN Y.TableID = 4 AND t4.Col1 IS NOT NULL THEN t4.Col1 
      WHEN Y.TableID = 5 AND t5.Col4 IS NOT NULL THEN t5.Col4 
      END 
    FROM Table X 
    JOIN Table Y ON X.ID = Y.XID 
LEFT JOIN TABLEFOUR t4 ON t4.id = y.fileid 
LEFT JOIN TABLEFIVE t5 ON t5.id = y.fileid 
+0

Полностью забыл о левых объединениях, извините, ребята, за этот вопрос n00b. Легко исправить. :) –

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