没有连接操作或用户定义对象的 TSQL 交错序列
TSQL Interleaved sequence without join operations or user defined objects
是否可以在不使用连接和用户定义的函数或过程的情况下创建一个第一个值和最后一个值依次出现直到数据集为空的交错序列?
code type model price
1 Hats 1298 700,00
1 Shoes 1232 600,00
1 Pants 1276 400,00
2 Hats 1321 970,00
2 Shoes 1121 850,00
2 Pants 1433 270,00
3 Hats 1750 1200,00
3 Shoes 1233 600,00
3 Pants 1434 290,00
4 Hats 1298 1050,00
4 Shoes 1121 850,00
4 Pants 1401 150,00
5 Hats 1752 1150,00
5 Shoes 1121 850,00
5 Pants 1408 270,00
6 Hats 1298 950,00
6 Shoes 1233 950,00
6 Pants 1288 400,00
7 Shoes 1232 400,00
8 Shoes 1232 350,00
9 Shoes 1232 350,00
10 Shoes 1260 350,00
11 Shoes 1233 980,00
12 Shoes 1233 970,00
我在行之间添加了额外的空格以获得交错序列的想法。
您想从最低编码项 (asc) 获得奇数值,从最高编码项 (desc) 获得偶数值。您还想按帽子、鞋子和裤子订购类型。
code type model price
1 Hats 1298 700,00
1 Shoes 1232 600,00
1 Pants 1276 400,00
6 Hats 1298 950,00
12 Shoes 1233 970,00
6 Pants 1288 400,00
2 Hats 1321 970,00
2 Shoes 1121 850,00
2 Pants 1433 270,00
5 Hats 1752 1150,00
11 Shoes 1233 980,00
5 Pants 1408 270,00
3 Hats 1750 1200,00
3 Shoes 1233 600,00
3 Pants 1434 290,00
4 Hats 1298 1050,00
10 Shoes 1260 350,00
4 Pants 1401 150,00
4 Shoes 1121 850,00
9 Shoes 1232 350,00
5 Shoes 1121 850,00
8 Shoes 1232 350,00
6 Shoes 1233 950,00
7 Shoes 1232 400,00
现在我想到了包含连接的解决方案,但我正在寻找无需使用它也能工作的解决方案。
我使用连接的解决方案:
with cteasc as
(
select
ROW_NUMBER() over(order by code,charindex(type, 'HatsShoesPants'))id
,(ROW_NUMBER() over(partition by type order by code,charindex(type, 'HatsShoesPants')) + 1) / 2 offsetasc
,code,model,price,type
from mydata
),
ctedsc as
(
select
ROW_NUMBER() over (partition by type order by code desc)id
,code,model,price,type
from cteasc
)
select t1.id
,case
when t1.code%2=1
then LAG(t1.type,t1.code-t1.offsetasc,t1.type)over(partition by t1.type order by t1.id)
else LAG(t2.type,t1.code-t1.offsetasc,t1.type)over(partition by t1.type order by t1.id)
end type
,case
when t1.code%2=1
then LAG(t1.model,t1.code-t1.offsetasc,t1.model)over(partition by t1.type order by t1.id)
else LAG(t2.model,t1.code-t1.offsetasc,t1.model)over(partition by t1.type order by t1.id)
end model
,case
when t1.code%2=1
then LAG(t1.price,t1.code-t1.offsetasc,t1.price)over(partition by t1.type order by t1.id)
else LAG(t2.price,t1.code-t1.offsetasc,t1.price)over(partition by t1.type order by t1.id)
end price
from
cteasc t1
join ctedsc t2
on t1.code = t2.id
and t1.type = t2.type
我们的想法是生成两个序列:
- 行号为 1、3、5 的升序项...
- 行号为 2、4、6 的降序项...
然后,我们只需要 UNION ALL
序列并对它们进行排序。
with ascItems as (
select *, row_number() over (order by someCol ASC) r * 2 - 1 as r from T
)
, descItems as (
select *, row_number() over (order by someCol DESC) r * 2 as r from T
)
select * from ascItems
union all
select * from descItems
order by r
这应该要求 table T 可以排序两次(按索引或按 2xsorting)。 UNION ALL
应该表现为廉价的合并连接。
是否可以在不使用连接和用户定义的函数或过程的情况下创建一个第一个值和最后一个值依次出现直到数据集为空的交错序列?
code type model price
1 Hats 1298 700,00
1 Shoes 1232 600,00
1 Pants 1276 400,00
2 Hats 1321 970,00
2 Shoes 1121 850,00
2 Pants 1433 270,00
3 Hats 1750 1200,00
3 Shoes 1233 600,00
3 Pants 1434 290,00
4 Hats 1298 1050,00
4 Shoes 1121 850,00
4 Pants 1401 150,00
5 Hats 1752 1150,00
5 Shoes 1121 850,00
5 Pants 1408 270,00
6 Hats 1298 950,00
6 Shoes 1233 950,00
6 Pants 1288 400,00
7 Shoes 1232 400,00
8 Shoes 1232 350,00
9 Shoes 1232 350,00
10 Shoes 1260 350,00
11 Shoes 1233 980,00
12 Shoes 1233 970,00
我在行之间添加了额外的空格以获得交错序列的想法。
您想从最低编码项 (asc) 获得奇数值,从最高编码项 (desc) 获得偶数值。您还想按帽子、鞋子和裤子订购类型。
code type model price
1 Hats 1298 700,00
1 Shoes 1232 600,00
1 Pants 1276 400,00
6 Hats 1298 950,00
12 Shoes 1233 970,00
6 Pants 1288 400,00
2 Hats 1321 970,00
2 Shoes 1121 850,00
2 Pants 1433 270,00
5 Hats 1752 1150,00
11 Shoes 1233 980,00
5 Pants 1408 270,00
3 Hats 1750 1200,00
3 Shoes 1233 600,00
3 Pants 1434 290,00
4 Hats 1298 1050,00
10 Shoes 1260 350,00
4 Pants 1401 150,00
4 Shoes 1121 850,00
9 Shoes 1232 350,00
5 Shoes 1121 850,00
8 Shoes 1232 350,00
6 Shoes 1233 950,00
7 Shoes 1232 400,00
现在我想到了包含连接的解决方案,但我正在寻找无需使用它也能工作的解决方案。
我使用连接的解决方案:
with cteasc as
(
select
ROW_NUMBER() over(order by code,charindex(type, 'HatsShoesPants'))id
,(ROW_NUMBER() over(partition by type order by code,charindex(type, 'HatsShoesPants')) + 1) / 2 offsetasc
,code,model,price,type
from mydata
),
ctedsc as
(
select
ROW_NUMBER() over (partition by type order by code desc)id
,code,model,price,type
from cteasc
)
select t1.id
,case
when t1.code%2=1
then LAG(t1.type,t1.code-t1.offsetasc,t1.type)over(partition by t1.type order by t1.id)
else LAG(t2.type,t1.code-t1.offsetasc,t1.type)over(partition by t1.type order by t1.id)
end type
,case
when t1.code%2=1
then LAG(t1.model,t1.code-t1.offsetasc,t1.model)over(partition by t1.type order by t1.id)
else LAG(t2.model,t1.code-t1.offsetasc,t1.model)over(partition by t1.type order by t1.id)
end model
,case
when t1.code%2=1
then LAG(t1.price,t1.code-t1.offsetasc,t1.price)over(partition by t1.type order by t1.id)
else LAG(t2.price,t1.code-t1.offsetasc,t1.price)over(partition by t1.type order by t1.id)
end price
from
cteasc t1
join ctedsc t2
on t1.code = t2.id
and t1.type = t2.type
我们的想法是生成两个序列:
- 行号为 1、3、5 的升序项...
- 行号为 2、4、6 的降序项...
然后,我们只需要 UNION ALL
序列并对它们进行排序。
with ascItems as (
select *, row_number() over (order by someCol ASC) r * 2 - 1 as r from T
)
, descItems as (
select *, row_number() over (order by someCol DESC) r * 2 as r from T
)
select * from ascItems
union all
select * from descItems
order by r
这应该要求 table T 可以排序两次(按索引或按 2xsorting)。 UNION ALL
应该表现为廉价的合并连接。