我们需要使用以下规则为所有行分配行号
示例:
>>>train.shape
(2,3)
>>>train.shape[0] # will display number of rows
2
>>>train.shape[1] # will display number of columns
3
应输出
ID GMD IsPinned
1 2.5 0
2 0 1
3 2 0
4 4 1
5 3 0
请注意,Id的2和4的行号保持不变,因为它们分别固定为2和4的值,即使GMD不在任何顺序 使用GMD desc对ID的其余1、3和5行编号进行排序
我尝试使用RowNumber SQL 2012,但是它从其位置推送固定的项目
答案 0 :(得分:1)
这是一种基于集合的方法来解决此问题。请注意,如果您的数据库中已经有一个Numbers
表,则不需要前一个CTE:
declare @t table (ID int,GMD decimal(5,2),IsPinned bit)
insert into @t (ID,GMD,IsPinned) values
(1,2.5,0), (2, 0 ,1), (3, 2 ,0), (4, 4 ,1), (5, 3 ,0)
;With Numbers as (
select ROW_NUMBER() OVER (ORDER BY ID) n from @t
), NumbersWithout as (
select
n,
ROW_NUMBER() OVER (ORDER BY n) as rn
from
Numbers
where n not in (select ID from @t where IsPinned=1)
), DataWithout as (
select
*,
ROW_NUMBER() OVER (ORDER BY GMD desc) as rn
from
@t
where
IsPinned = 0
)
select
t.*,
COALESCE(nw.n,t.ID) as RowNo
from
@t t
left join
DataWithout dw
inner join
NumbersWithout nw
on
dw.rn = nw.rn
on
dw.ID = t.ID
order by COALESCE(nw.n,t.ID)
希望我的名字可以清楚地说明我们在做什么。当您可能期望使用SELECT
表达式时,通过使用COALESCE
获得最终的RowNo
,我对最后的CASE
有点厚颜无耻。但这是可行的,因为DataWithout
CTE的内容被定义为仅存在于未固定的项目中,从而导致最终的LEFT JOIN
失败。
结果:
ID GMD IsPinned RowNo
----------- --------------------------------------- -------- --------------------
5 3.00 0 1
2 0.00 1 2
1 2.50 0 3
4 4.00 1 4
3 2.00 0 5
第二种效果可能更好(但从不假设,请始终进行测试):
declare @t table (ID int,GMD decimal(5,2),IsPinned bit)
insert into @t (ID,GMD,IsPinned) values
(1,2.5,0), (2, 0 ,1), (3, 2 ,0), (4, 4 ,1), (5, 3 ,0)
;With Numbers as (
select ROW_NUMBER() OVER (ORDER BY ID) n from @t
), NumbersWithout as (
select
n,
ROW_NUMBER() OVER (ORDER BY n) as rn
from
Numbers
where n not in (select ID from @t where IsPinned=1)
), DataPartitioned as (
select
*,
ROW_NUMBER() OVER (PARTITION BY IsPinned ORDER BY GMD desc) as rn
from
@t
)
select
dp.ID,dp.GMD,dp.IsPinned,
CASE WHEN IsPinned = 1 THEN ID ELSE nw.n END as RowNo
from
DataPartitioned dp
left join
NumbersWithout nw
on
dp.rn = nw.rn
order by RowNo
在第三个CTE中,通过引入PARTITION BY
并删除WHERE
子句,我们确保已拥有所有数据行,因此在最终版本中无需重新连接至原始表导致出现这种变体。
答案 1 :(得分:0)
这将起作用:
CREATE TABLE Table1
("ID" int, "GMD" number, "IsPinned" int)
;
INSERT ALL
INTO Table1 ("ID", "GMD", "IsPinned")
VALUES (1, 2.5, 0)
INTO Table1 ("ID", "GMD", "IsPinned")
VALUES (2, 0, 1)
INTO Table1 ("ID", "GMD", "IsPinned")
VALUES (3, 2, 0)
INTO Table1 ("ID", "GMD", "IsPinned")
VALUES (4, 4, 1)
INTO Table1 ("ID", "GMD", "IsPinned")
VALUES (5, 3, 0)
SELECT * FROM dual
;
select * from (select "ID","GMD","IsPinned",rank from(select m.*,rank()over(order by
"ID" asc) rank from Table1 m where "IsPinned"=1)
union
(select "ID","GMD","IsPinned",rank from (select t.*,rank() over(order by "GMD"
desc)-1 rank from (SELECT * FROM Table1)t)
where "IsPinned"=0) order by "GMD" desc) order by rank ,GMD;
输出:
2 0 1 1
5 3 0 1
1 2.5 0 2
4 4 1 2
3 2 0 3
答案 2 :(得分:0)
您可以尝试查询吗
CREATE TABLE Table1
(ID int, GMD numeric (18,2), IsPinned int);
INSERT INTO Table1 (ID,GMD, IsPinned)
VALUES (1, 2.5, 0),
(2, 0, 1),
(3, 2, 0),
(4, 4, 1),
(5, 3, 0)
select *, row_number () over(partition by IsPinned order by (case when IsPinned =0 then GMD else id end) ) [CustOrder] from Table1
答案 3 :(得分:0)
这花了更长的时间,而我认为,问题是row_number可以解决查询。我们需要先按id区分row_numbers,然后才能应用while循环或游标或任何迭代,在本例中,我们将仅使用while循环。
dbo.test(您可以用表名替换test)
1 2.5 False
2 0 True
3 3 False
4 4 True
6 2 False
这是我为达到目标而编写的查询,如果您有任何困难要告诉我,我会在每个操作下添加注释。
查询:
--user data table
DECLARE @userData TABLE
(
id INT NOT NULL,
gmd FLOAT NOT NULL,
ispinned BIT NOT NULL,
rownumber INT NOT NULL
);
--final result table
DECLARE @finalResult TABLE
(
id INT NOT NULL,
gmd FLOAT NOT NULL,
ispinned BIT NOT NULL,
newrownumber INT NOT NULL
);
--inserting to uer data table from the table test
INSERT INTO @userData
SELECT t.*,
Row_number()
OVER (
ORDER BY t.id ASC) AS RowNumber
FROM test t
--creating new table for ids of not pinned
CREATE TABLE #ids
(
rn INT,
id INT,
gmd FLOAT
)
-- inserting into temp table named and adding gmd by desc
INSERT INTO #ids
(rn,
id,
gmd)
SELECT DISTINCT Row_number()
OVER(
ORDER BY gmd DESC) AS rn,
id,
gmd
FROM @userData
WHERE ispinned = 0
--declaring the variable to loop through all the no pinned items
DECLARE @id INT
DECLARE @totalrows INT = (SELECT Count(*)
FROM #ids)
DECLARE @currentrow INT = 1
DECLARE @assigningNumber INT = 1
--inerting pinned items first
INSERT INTO @finalResult
SELECT ud.id,
ud.gmd,
ud.ispinned,
ud.rownumber
FROM @userData ud
WHERE ispinned = 1
--looping through all the rows till all non-pinned items finished
WHILE @currentrow <= @totalrows
BEGIN
--skipping pinned numers for the rows
WHILE EXISTS(SELECT 1
FROM @finalResult
WHERE newrownumber = @assigningNumber
AND ispinned = 1)
BEGIN
SET @assigningNumber = @assigningNumber + 1
END
--getting row by the number
SET @id = (SELECT id
FROM #ids
WHERE rn = @currentrow)
--inserting the non-pinned item with new row number into the final result
INSERT INTO @finalResult
SELECT ud.id,
ud.gmd,
ud.ispinned,
@assigningNumber
FROM @userData ud
WHERE id = @id
--going to next row
SET @currentrow = @currentrow + 1
SET @assigningNumber = @assigningNumber + 1
END
--getting final result
SELECT *
FROM @finalResult
ORDER BY newrownumber ASC
--dropping table
DROP TABLE #ids
输出: