Один SQL SELECT Возвращает несколько строк из одной строки таблицы - PullRequest
6 голосов
/ 20 мая 2009

У нас есть таблица, которая имеет вид:

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.

Ответы [ 9 ]

9 голосов
/ 20 мая 2009

Дайте 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 операциях). Это не должно иметь никакого значения для данных (поскольку ваши идентификаторы ДОЛЖНЫ отличаться), но это может немного ускорить его.

4 голосов
/ 20 мая 2009

Это работает в 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. (Использование объединения для генерации строк переносимо на другие БД)

2 голосов
/ 20 мая 2009

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

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
2 голосов
/ 20 мая 2009

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

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
0 голосов
/ 24 июля 2013

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

0 голосов
/ 23 июля 2013

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

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, который будет работать с любой базой данных.

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

0 голосов
/ 20 мая 2009

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

0 голосов
/ 20 мая 2009

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

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

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

0 голосов
/ 20 мая 2009

Если вы используете 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
...