我有下表
ID | QUANTITY
------------
1 | 3
2 | 2
我需要的是
ID | Ref No.
------------
1 | MyRef1
1 | MyRef2
1 | MyRef3
2 | AnotherRef1
2 | AnotherRef2
即。我需要使用与A中的数量相同的行数生成表B,并使用递增的参考号。在每一行。
我可以用游标或UDF来做,但有更优雅的解决方案吗?
答案 0 :(得分:17)
我会假设
类似的东西:
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
答案 1 :(得分:7)
这将在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
答案 2 :(得分:2)
以下为您提供了正确的行数,但我的观察结果与@Dems相同:您如何确定MyRef
和AnotherRef
?
请注意,这至少需要SQL Server 2005
;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
答案 3 :(得分:0)
单击选择按列TableA.quantity生成行。仅使用ISO / ANSI SQL标准语法2003(DB必须支持窗口功能)。
TableA定义:
|----|----------|---------------|
| 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
答案 4 :(得分:0)
只要tblNumbers中的记录数超过TableA中找到的Quantity值的最大值,Numbers表解决方案就可以在MS Access中使用:
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等开头。
答案 5 :(得分:0)
这也可以解决问题。它使用递归,创建一个包含1-100行的表。
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == 111 && resultCode== Activity.RESULT_OK){
val selectedfile=data?.data
val inputStream: InputStream = contentResolver!!.openInputStream(data!!.data!!)!!
val inputString = inputStream.bufferedReader()
inputString.readLine()
inputString.readLine()
inputString.readLine()
inputString.readLine()
inputString.readLine()
val iterator = inputString.readLine().lineSequence().iterator()
while (iterator.hasNext()) {
val line = inputString.readLine()
val lineV = "\\s+".toRegex()
if (line != null) {
var (nume, lat, lats, ns, long, longs, we) = line.split(lineV)
val hashLat = HashMap<String, Float>()
val hashCard =HashMap<String,String>()
if (nume == "") { nume = "wpnume" } else { nume }
//hashLat.put("nume", nume)
hashLat.put("lat", lat.toFloat())
hashLat.put("lats", lats.toFloat())
hashCard.put("ns", ns)
hashLat.put("lng", long.toFloat())
hashLat.put("lngs", longs.toFloat())
hashCard.put("we", we)
println(hashLat) //output something like:
{lats=24.194, lat=57.0, lng=21.0, lngs=31.824}
{lats=24.413, lat=57.0, lng=21.0, lngs=31.53}
{lats=25.14, lat=57.0, lng=21.0, lngs=30.55}
{lats=26.122, lat=57.0, lng=21.0, lngs=25.507}
{lats=25.954, lat=57.0, lng=21.0, lngs=24.712}
答案 6 :(得分:0)
生成@n 行的一种非常简单的方法如下
DECLARE @n INT= 50
SELECT
RowId = ROW_NUMBER()OVER(ORDER BY (SELECT 0))
FROM
(VALUES(CAST(REPLICATE('<a/>',@n) AS XML)))xmlLines(xmlLines)
CROSS APPLY xmlLines.nodes('*')Lines(Line)
这个方法是有限制的。 由于 REPLICATE 函数生成最大长度为 8000 个字符的字符串, 生产线最多可达2000条。 要获得更大的数字,您可以使用以下方法:
DECLARE @n INT= 50;
WITH Block AS(
SELECT
RowId = ROW_NUMBER()OVER(ORDER BY (SELECT 0))
,MaxBlockSize
FROM
(VALUES(128))MaxBlockSize(MaxBlockSize)
CROSS APPLY (VALUES(CAST(REPLICATE('<a/>',CASE WHEN @n<MaxBlockSize THEN @n ELSE MaxBlockSize END) AS XML)))xmlLines(xmlLines)
CROSS APPLY xmlLines.nodes('*')Lines(Line)
)
, Blocks AS(
SELECT
RowId
,NextStart = RowId*MaxBlockSize
FROM
Block
WHERE
RowId<=MaxBlockSize
UNION ALL
SELECT
RowId = Blocks.NextStart+Block.RowId
,NextStart = (Blocks.NextStart+Block.RowId)*MaxBlockSize
FROM
Blocks
CROSS APPLY Block
WHERE
Blocks.NextStart+Block.RowId<=@n
)
SELECT RowId FROM Blocks ORDER BY RowId
MaxBlockSize 的取值选择为 128(理论上最大为 2000)已减少为 128 为查询效率的原因