Необходимо создать n строк на основе значения в столбце
У меня есть следующая таблица
ТАБЛИЦА A
ID | QUANTITY
------------
1 | 3
2 | 2
Мне нужно
ТАБЛИЦА B
ID | Ref No.
------------
1 | MyRef1
1 | MyRef2
1 | MyRef3
2 | AnotherRef1
2 | AnotherRef2
то есть. Мне нужно создать таблицу B с тем же количеством строк, что и количество в с восходящим номером ref. на каждой строке.
Я могу сделать это с помощью курсоров или UDF, но есть ли более изящное решение?
Ответы
Ответ 1
Я приду
- MyRef и т.д. Является столбцом в таблице A
- У вас есть таблица чисел
Что-то вроде:
SELECT * INTO #TableA
FROM
(
SELECT 1 AS ID, 3 AS QUANTITY, 'MyRef' AS refColumn
UNION ALL
SELECT 2, 2, 'AnotherRef'
) T
;WITH Nbrs ( Number ) AS (
SELECT 1 UNION ALL
SELECT 1 + Number FROM Nbrs WHERE Number < 99
)
SELECT
A.ID, A.refColumn + CAST(N.Number AS varchar(10))
FROM
#TableA A
JOIN
Nbrs N ON N.Number <= A.QUANTITY
Ответ 2
Это создаст количество строк, которое вы хотите, в SQL Server 2005+, хотя я точно не знаю, как вы хотите определить, какие должны быть MyRef и AnotherRef...
WITH
expanded
AS
(
SELECT id, Quantity FROM myTable
UNION ALL
SELECT id, Quantity - 1 FROM expanded WHERE Quantity > 1
)
SELECT
*,
ROW_NUMBER() OVER (ORDER BY id, Quantity) AS unique_ref
FROM
expanded
ORDER BY
id,
Quantity
Ответ 3
Ниже приведено правильное количество строк, но мое наблюдение такое же, как @Dems: как вы определяете MyRef
и AnotherRef
?
Обратите внимание, что для этого требуется, по крайней мере, SQL Server 2005
Заявление SQL
;WITH TableA (ID, Quantity) AS (
SELECT 1, 3
UNION ALL SELECT 2, 2
)
, q AS (
SELECT ID
, Number = 1
, Quantity
FROM TableA
UNION ALL
SELECT ID
, Number = Number + 1
, Quantity
FROM q
WHERE Quantity > Number
)
SELECT ID
, CASE WHEN ID = 1 THEN 'MyRef' + CAST(Number AS VARCHAR(1))
WHEN ID = 2 THEN 'AnotherRef' + CAST(Number AS VARCHAR(1))
END AS [Ref No.]
FROM q
ORDER BY
ID
Выход
ID Ref No.
1 MyRef1
1 MyRef2
1 MyRef3
2 AnotherRef1
2 AnotherRef2
Ответ 4
Один выбор для создания строк по столбцу TableA.quantity. Используется только ISO/ANSI SQL Standard синтаксис 2003 (БД должна поддерживать оконную функцию).
Таблица A определение:
|----|----------|---------------|
| id | quantity | another_value |
|----|----------|---------------|
| 1 | 3| value_a |
| 2 | 2| value_b |
| 3 | 6| value_c |
|----|----------|---------------|
CREATE TABLE TableA AS
(SELECT 1 as ID, 3 AS quantity, 'value_a' AS another_value
UNION SELECT 2, 2, 'value_b'
UNION SELECT 3, 6, 'value_c');
Следующий запрос можно использовать для значения количества до 1000. Для количества до 10000 расширить запрос оператором CROSS JOIN ten AS rank10000
...
SELECT
ROW_NUMBER() OVER(order by id) as unique_id,
id as original_id,
another_value || ROW_NUMBER() OVER (PARTITION BY id) as another_value
FROM TableA
INNER JOIN
(SELECT row_number() OVER () AS rnum FROM
(WITH ten AS (SELECT 1 AS id UNION SELECT 2
UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6
UNION SELECT 7 UNION SELECT 8
UNION SELECT 9 UNION SELECT 10)
SELECT *
FROM ten AS rank10
CROSS JOIN ten AS rank100
CROSS JOIN ten AS rank1000
) helper
) help ON help.rnum <= TableA.quantity
Результат SQL:
|-----------|-------------|---------------|
| unique_id | original_id | another_value |
|-----------|-------------|---------------|
| 1 | 1 | value_a1 |
| 2 | 1 | value_a2 |
| 3 | 1 | value_a3 |
| 4 | 2 | value_b1 |
| 5 | 2 | value_b2 |
| 6 | 3 | value_c1 |
| 7 | 3 | value_c2 |
| 8 | 3 | value_c3 |
| 9 | 3 | value_c4 |
| 10 | 3 | value_c5 |
| 11 | 3 | value_c6 |
|-----------|-------------|---------------|
Должно работать на PostgreSQL, Oracle или MSSQL (протестировано на PostgreSQL 9.0)
Отредактировано: оптимизированный запрос с использованием оператора WITH RECURSIVE (идея из MatBailie):
SELECT
ROW_NUMBER() OVER() as unique_id,
id as original_id,
another_value || ROW_NUMBER() OVER (PARTITION BY id) as another_value
FROM
(WITH RECURSIVE helper AS
(SELECT id, quantity, another_value FROM TableA
UNION ALL
SELECT id, quantity-1, another_value FROM helper WHERE quantity > 1
) SELECT * FROM helper ORDER BY id, quantity
) TableB
Ответ 5
Решение Table Table будет работать в MS Access, если количество записей в tblNumbers превышает максимальное количество значений, найденных в таблице A:
SELECT TableA.ID, TableA.Quantity, tblNumbers.RecNum
FROM TableA LEFT JOIN tblNumbers ON tblNumbers.RecNum <= TableA.Quantity
ORDER BY TableA.ID, tblNumbers.RecNum;
ПРИМЕЧАНИЕ: tblNumbers.RecNum - это длинное целое число, начиная с строки 1 = 1, строки 2 = 2 и т.д.
Ответ 6
Это также помогло бы. Он использует рекурсию, создает таблицу со строками 1-100.
WITH NBR ( NUM ) AS (
SELECT 1 UNION ALL
SELECT 1 + NUM FROM NBR
WHERE NUM < 100
)
SELECT * into NUMBERS from NBR