Есть ли в T-SQL UNION, эквивалентный FULL OUTER JOIN, который объединяет разнородные наборы столбцов? - PullRequest
2 голосов
/ 06 декабря 2009

Я пытаюсь сделать следующее:

SELECT col1, col2 FROM table1
UNION
SELECT col2, col3 FROM table2

С результатом:

col1, col2, col3
1   , 1   , NULL
NULL, 1   , 1

Объединение столбцов и строк возвращается. Вы могли бы думать об этом как об объединении, эквивалентном FULL OUTER JOIN.

Простой ответ на этот вопрос:

SELECT col1, col2, NULL AS col3 FROM table1
UNION
SELECT NULL AS col1, col2, col3 FROM table2

Это, однако, трудно сделать с динамическим T-SQL и dbo.sp_executesql, и результирующий запрос может быть слишком длинным, если задействовано большое количество UNIONS.

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

CREATE TABLE #temp ( col1 int, col2 int, col3 int )
INSERT INTO #temp ( col1, col2 ) SELECT col1, col2 FROM table1
INSERT INTO #temp ( col2, col3 ) SELECT col2, col3 FROM table2

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

Есть ли более простой способ сделать это?

Спасибо!

Ответы [ 4 ]

1 голос
/ 07 декабря 2009

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

Этот запрос даст вам список столбцов и их типов данных для конкретной таблицы:

SELECT @columnName = c.name AS columnName,
       @columnDataType = ty.name AS columnDataType
  FROM SYS.TABLES ta
  JOIN SYS.COLUMNS c ON c.object_id = ta.object_id
  JOIN SYS.TYPES ty ON ty.user_type_id = c.user_type_id
 WHERE ta.name = '[your_table_name]'

Заполняет переменные @columnName & @columnDataType, чтобы вы могли использовать их в другом месте.

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

Более простой подход - определить, какой запрос необходим для большинства ситуаций.
Грустная часть заключается в том, что когда вы спрашиваете, ответ, как правило, «все». Для этого ответа я бы изложил, что для поддержки всего необходимого количества валюты и времени. Подчеркните, что дешевле и быстрее разбить требование на управляемые порции - это также позволит вам получить обратную связь. Возможно, что никто никогда не будет использовать небольшое подмножество функций, или это совсем не то, что нужно пользователю. Научитесь управлять ожиданиями клиентов.

0 голосов
/ 13 декабря 2009

Я накинул полотенце на этот, написал кучу неприятных динамических T-SQL и выполнил его с помощью sp_executesql. Спасибо за помощь!

0 голосов
/ 07 декабря 2009

Поможет ли это (присоединение к некоторой фиктивной колонне) в некотором понимании?

declare @t1 table(col1 varchar(10),col2 varchar(10))
declare @t2 table(col2 varchar(10),col3 varchar(10))
insert into @t1 select '1','1' union all select '10','1'
insert into @t2 select '1',null union all select '10','1'

;with cte1 as(select ROW_NUMBER() over(order by getdate()) rn1, t1.* from @t1 t1)
,cte2 as(select ROW_NUMBER() over(order by getdate()) rn2, t2.* from @t2 t2)
select c1.col1,c1.col2,c2.col3
from cte1 c1 
full outer join cte2 c2
on c1.rn1 = c2.rn2

Выход:

col1    col2    col3
1   1   NULL
10  1   1
0 голосов
/ 06 декабря 2009

После быстрой попытки самое близкое, что я могу получить в T-SQL, не прыгая через множество пылающих обручей хакерства, это использовать FULL OUTER JOIN с ложным условием ... например,

DECLARE @TableA TABLE (Col1 INTEGER IDENTITY(1,1), Col2 INTEGER)
DECLARE @TableB TABLE (Col2 INTEGER IDENTITY(1,1), Col3 INTEGER)

INSERT @TableA VALUES (1)
INSERT @TableA VALUES (11)
INSERT @TableB VALUES (2)
INSERT @TableB VALUES (222)

SELECT *
FROM @TableA a
    FULL OUTER JOIN @TableB b ON 0 = 1

Вы увидите из результатов, что Col2 дважды включен в набор результатов ... он не объединен в один.

Мое предложение будет заключаться в том, чтобы обрабатывать это в вашем коде, а не в T-SQL - возвращать несколько наборов результатов в ваш вызывающий код и иметь дело с различными схемами. Если вам действительно нужно это как один набор результатов, может ли этот вызывающий код не объединить результаты в один?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...