Одиночный SQL SELECT. Возврат нескольких строк из одной строки таблицы.

StackOverflow https://stackoverflow.com/questions/887870

Вопрос

У нас есть таблица вида:

ID,Value1,Value2,Value3
1,2,3,4

Нам нужно преобразовать это в .

ID,Name,Value
1,'Value1',2
1,'Value2',3
1,'Value3',4

Есть ли умный способ сделать это в одном операторе SELECT (т.е. без UNION)?Имена столбцов Value1, Value2 и Value3 фиксированы и постоянны.

База данных — Oracle 9i.

Это было полезно?

Решение

Это работает на Oracle 10g:

select id, 'Value' || n as name,
       case n when 1 then value1 when 2 then value2 when 3 then value3 end as value
from (select rownum n
      from (select 1 from dual connect by level <= 3)) ofs, t

Я думаю, что в Oracle 9i были рекурсивные запросы?В любом случае, я почти уверен, что он поддерживает CASE, поэтому, даже если он не имеет рекурсивных запросов, вы можете вместо этого просто выполнить «(выбрать 1 из двойного объединения, все выбрать 2 из двойного объединения, все выбрать 3 из двойного) ofs».Злоупотребление рекурсивными запросами имеет более общий характер – для Oracle.(Однако использование объединений для создания строк можно переносить на другие БД)

Другие советы

Дать union выстрел.

select ID, 'Value1' as Name, Value1 as Value from table_name union all
select ID, 'Value2', Value2 as Value from table_name union all
select ID, 'Value3', Value3 as Value from table_name

order by ID, Name

с использованием union all означает, что сервер не будет выполнять distinct (что подразумевается union операции).Это не должно иметь никакого значения для данных (поскольку ваши идентификаторы, НАДЕЕМСЯ, должны быть другими), но это может немного ускорить процесс.

Можно сделать так, но это некрасиво:

SELECT id,'Value 1' AS name,value1 AS value FROM mytable
UNION
SELECT id,'Value 2' AS name,value2 AS value FROM mytable
UNION
SELECT id,'Value 3' AS name,value3 AS value FROM mytable

Объединение трех операторов выбора должно помочь:

SELECT ID, 'Value1', Value1 AS Value
FROM TABLE
UNION
SELECT ID, 'Value2', Value2 AS Value
FROM TABLE
UNION
SELECT ID, 'Value3', Value3 AS Value
FROM TABLE

Если вы используете SQL Server 2005+, вы можете использовать UNPIVOT.

CREATE TABLE #tmp ( ID int, Value1 int, Value2 int, Value3 int)

INSERT INTO #tmp (ID, Value1, Value2, Value3) VALUES (1, 2, 3, 4)

SELECT
    *
FROM
    #tmp

SELECT
    *
FROM
    #tmp
UNPIVOT
(
    [Value] FOR [Name] IN (Value1, Value2, Value3)
) uPIVOT

DROP TABLE #tmp

UNION ALL, как предполагали другие, вероятно, является лучшим выбором в SQL.Вы также можете рассмотреть возможность обработки этого во внешнем интерфейсе в зависимости от ваших конкретных требований.

Синтаксис CTE может отличаться для Oracle (я запускал его в Teradata), но я использовал CTE только для предоставления тестовых данных, а именно 1, 2, 3 и 4.Вместо этого вы можете использовать временную таблицу.Фактический оператор выбора представляет собой простой стандартный SQL, и он применим к любой реляционной базе данных.

Для Sql Server рассмотрите UNPIVOT как альтернативу UNION:

SELECT id, value, colname
FROM #temp t
UNPIVOT (Value FOR ColName IN (value1,value2,value3)) as X

Это также вернет имя столбца.Я не уверен, для чего используется X, но вы не можете его пропустить.

Попробуй это:

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

with TEST_CTE (ID) as

(select * from (select '1' as a) as aa  union all
select * from (select '2' as b) as bb  union all
select * from (select '3' as c) as cc  union all
select * from (select '4' as d) as dd )

select a.ID, 'Value'|| a.ID, b.ID
from TEST_CTE a, TEST_CTE b
where b.ID = (select min(c.ID) from TEST_CTE c where c.ID > a.ID)

Вот набор результатов:

1   Value1  2

2   Value2  3

3   Value3  4

Наслаждаться!

Некоторые запоздалые мысли.

^^^ Синтаксис CTE в Oracle может отличаться.Я мог запустить его только в Teradata.Вы можете заменить ее временной таблицей или исправить синтаксис, чтобы сделать ее совместимой с Oracle.Оператор select — это простой SQL, который будет работать с любой базой данных.

^^^ Еще одно замечание.Если поле идентификатора является числовым, вам может потребоваться преобразовать его в CHAR, чтобы объединить его со значением.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top