Выбор нескольких строк из одной строки в SQL - PullRequest
3 голосов
/ 13 февраля 2011

У меня есть следующий вывод из нескольких таблиц

id    b   c   b     e    b     g  
abc  2   123  3   321   7   876  
abd  2   456  3   452   7   234  
abe  2   0    3   123   7   121  
abf  2   NULL 3   535   7   1212  

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

insert into resulttable values (id,b,c), (id,b,e) etc.

Для этого мне нужно сделать выбор, который дает мне

id,b,c
id,b,e etc

Я тоже не против избавиться от b, так как его можно выбрать с помощью запроса c #.

Как можноЯ добиваюсь того же, используя один запрос в SQL.Опять же, обратите внимание, это не таблица, это вывод из разных таблиц

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

select b.a, b.c
union all
select b.d,b.e from  (select a,c,d,e from <set of join>)  b

Но, к сожалению, это не работает

Ответы [ 4 ]

2 голосов
/ 13 февраля 2011

Здесь #tmporigin относится к вашему исходному запросу, который производит данные в вопросе. Просто замените имя таблицы на подзапрос.

insert into resulttable
select
 o.id,
 case a.n when 1 then b1 when 2 then b2 else b3 end,
 case a.n when 1 then c when 2 then e else g end
from #tmporigin o
cross join (select 1n union all select 2 union all select 3) a


Оригинальный ответ ниже, с использованием CTE и объединения, требующего оценки CTE 3 раза

У меня следующий вывод из нескольких таблиц

Так что установите этот запрос как общее табличное выражение

;WITH CTE AS (
   -- the query that produces that output
)
select id,b1,c from CTE
union all
select id,b2,e from CTE
union all
select id,b3,g from CTE

ПРИМЕЧАНИЕ - Вопреки распространенному мнению, ваш CTE, хотя и написан удобно один раз, запускается трижды в приведенном выше запросе, один раз для каждой из всех частей объединения.

ПРИМЕЧАНИЕ ТАКЖЕ , что если вы на самом деле назовете 3 столбца "b" (буквально), то нет способа определить, на какой b вы ссылаетесь во всем, что пытается ссылаться на результаты - фактически SQL Server не позволит вам использовать запрос в CTE или подзапросе.

В следующем примере показано, как выполнить вышеизложенное, а также (если вы показываете план выполнения), показывающее, что CTE запускается 3 раза! (строки между --- BELOW HERE и --- ABOVE HERE - это макет original query, который выдает результат в вопросе.

if object_id('tempdb..#eav') is not null drop table #eav
;
create table #eav (id char(3), b int, v int)
insert #eav select 'abc', 2, 123
insert #eav select 'abc', 3, 321
insert #eav select 'abc', 7, 876
insert #eav select 'abd', 2, 456
insert #eav select 'abd', 3, 452
insert #eav select 'abd', 7, 234
insert #eav select 'abe', 2, 0
insert #eav select 'abe', 3, 123
insert #eav select 'abe', 7, 121
insert #eav select 'abf', 3, 535
insert #eav select 'abf', 7, 1212

;with cte as (
---- BELOW HERE
    select id.id, b1, b1.v c, b2, b2.v e, b3, b3.v g
    from
    (select distinct id, 2 as b1, 3 as b2, 7 as b3 from #eav) id
    left join #eav b1 on b1.b=id.b1 and b1.id=id.id
    left join #eav b2 on b2.b=id.b2 and b2.id=id.id
    left join #eav b3 on b3.b=id.b3 and b3.id=id.id
---- ABOVE HERE
)
select b1, c from cte
union all
select b2, e from cte
union all
select b3, g from cte
order by b1

Было бы лучше сохранить данные во временную таблицу, прежде чем делать выбор union all.

2 голосов
/ 13 февраля 2011
INSERT resulttable
SELECT id, b, c
FROM original
UNION
SELECT id, b, e
FROM original

В вашем примере есть несколько столбцов с именем 'b', что запрещено ...

0 голосов
/ 13 февраля 2011

Я не уверен, правильно ли я понял Вашу проблему, но какое-то время я использовал что-то подобное:

допустим, у нас есть таблица

ID Val1 Val2<bR> 1 A B<Br> 2 C D

чтобы получить результат вроде

ID Val<br> 1 A<br> 1 B<br> 2 C<br> 2 D

Вы можете использовать запрос:

select ID, case when i=1 then Val1 when i=2 then Val2 end as Val
from table
left join ( select 1 as i union all select 2 as i ) table_i on i=i

, который просто объединит таблицу с подзапросом, содержащим два значения, и создаст декартово произведение. В результате все строки будут удвоены (или умножены на количество значений, которые будет иметь подзапрос). Вы можете варьировать количество значений в зависимости от того, сколько вариантов строки вам понадобится. В зависимости от значения i, Val будет Val1 или Val2 из исходной таблицы. Если вы увидите план выполнения, появится предупреждение о том, что у соединения нет предикатов соединения (из-за i = i), но это нормально - мы этого хотим. Это делает запросы немного большими (с точки зрения текста) из-за всего случая, когда, но довольно легко читать, если отформатирован правильно. Мне это нужно для глупых таблиц, таких как «BigID, smallID1, smallID2 ... smallID11», которые были распределены по многим столбцам, я не знаю почему. Надеюсь, поможет. О, я использую статическую таблицу с 10000 числами, поэтому я просто использую

join tab10k on i<=10

для 10х рядов. Прошу прощения за глупое форматирование, я здесь новенький.

0 голосов
/ 13 февраля 2011

Вместо этого, который не работает, как вы знаете

select b.a, b.c
union all
select b.d,b.e from  (select a,c,d,e from <set of join>)  b

Вы можете сделать это.Союз с повторным подвыбором

select b.a, b.c from (select a,c,d,e from <set of join>)  b
union all
select b.d, b.e from (select a,c,d,e from <set of join>)  b

Или вот этим.Повторное использование cte.

with cte as
(select a,c,d,e from <set of join>)
select b.a, b.c from cte b
union all
select b.d, b.e from cte b

Или используйте временную переменную таблицы.

declare @T table (a int, c int, d int, e int)
insert into @T values
select a,c,d,e from <set of join>

select b.a, b.c from @T  b
union all
select b.d, b.e from @T  b

Этот код не тестировался, поэтому в нем может быть любое количество опечаток.

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