Sql server 按行值划分
当某一行具有某一值时,我需要对输出表进行分区。我有:Sql server 按行值划分,sql-server,database,tsql,Sql Server,Database,Tsql,当某一行具有某一值时,我需要对输出表进行分区。我有: ID|Value|User ------------- 1 |A |Rick 2 |A |Rick 3 |B |Rick 7 |A |Rick 8 |C |Rick 4 |A |Joe 5 |B |Joe 6 |B |Joe 我需要为每个单独的用户对表进行分区,当值=A时,我需要的是: Row|ID|Value|User ------------------ 1 |1 |A |Rick
ID|Value|User
-------------
1 |A |Rick
2 |A |Rick
3 |B |Rick
7 |A |Rick
8 |C |Rick
4 |A |Joe
5 |B |Joe
6 |B |Joe
我需要为每个单独的用户对表进行分区,当值=A时,我需要的是:
Row|ID|Value|User
------------------
1 |1 |A |Rick
1 |2 |A |Rick
2 |3 |B |Rick
1 |7 |A |Rick
2 |8 |C |Rick
1 |4 |A |Joe
2 |5 |B |Joe
3 |6 |B |Joe
每个值都有自己的ID
我试过这样的方法:
SELECT ROW_NUMBER() OVER(PARTITION BY User, Value = A ORDER BY ID ASC) AS Row, Value, User FROM...
SELECT ROW_NUMBER() OVER(PARTITION BY User, WHERE Value = A ORDER BY ID ASC) AS Row, Value, User FROM...
etc
但是,如果可能的话,我似乎不知道如何正确地书写它。似乎你想要的只是一个密集的等级: 注意用户是T-SQL中的保留关键字。我强烈建议您为列选择不同的名称,否则您必须对其进行分隔和标识。行和值当前未保留,但它们列为,建议避免使用 编辑:看起来,实际上它的'A'是1,然后也会增加。这很混乱,但你可以这样做:
SELECT CASE [Value]
WHEN 'A' THEN 1
ELSE ROW_NUMBER() OVER (PARTITION BY [User] ORDER BY [Value]) -
COUNT(CASE [Value] WHEN 'A' THEN 1 END) OVER (PARTITION BY [User]) + 1
END AS [Row],
V.[Value],
V.[User]
FROM (VALUES ('A', 'Rick'),
('A', 'Rick'),
('B', 'Rick'),
('C', 'Rick'),
('A', 'Joe '),
('B', 'Joe '),
('B', 'Joe ')) V ([Value], [User]);
这假定始终至少有一行带有“A”
编辑2:好的,目标帖子又被移动了,这就是你想要的。如果他们再次移动,您需要修改解决方案,但:
WITH YourTable AS(
SELECT V.ID,
V.Value,
V.[User]
FROM (VALUES(1,'A','Rick'),
(2,'A','Rick'),
(3,'B','Rick'),
(7,'A','Rick'),
(8,'C','Rick'),
(4,'A','Joe '),
(5,'B','Joe '),
(6,'B','Joe '))V(ID,[Value],[User])),
Grps AS(
SELECT YT.ID,
YT.Value,
YT.[User],
COUNT(CASE YT.[Value] WHEN 'A' THEN 1 END) OVER(PARTITION BY YT.[User] ORDER BY YT.ID) AS Grp
FROM YourTable YT)
SELECT ID,
CASE G.[Value]
WHEN 'A' THEN 1
ELSE ROW_NUMBER() OVER (PARTITION BY G.[User], G.Grp ORDER BY G.[Value]) -
COUNT(CASE G.[Value] WHEN 'A' THEN 1 END) OVER (PARTITION BY G.[User], G.Grp) + 1
END AS [Row],
G.[Value],
G.[User]
FROM Grps G
ORDER BY G.[User], G.ID;
这个怎么样-A总是1,如果出现A,我将行卷回1,如果不是A,我总是增加1
With CTE AS (select *, row_number() OVER (order by [user], value) as RN from theTable)
select CASE WHEN C1.Value = 'A' THEN 1 ELSE 1 + C1.RN - C.RN END [row] , * from
CTE C1 OUTER APPLY
(SELECT TOP 1 RN FROM CTE C2
WHERE C2.RN < C1.RN AND C2.Value = 'A'
ORDER BY C2.RN DESC) C
我不认为稠密秩会像你的例子中那样工作,B会有相同的值
2 |B |Joe
2 |B |Joe
而不是
2 |B |Joe
3 |B |Joe
我想出的最好的方法是两遍法
使用普通行号->按c.name按c.value按顺序划分的行号作为rn
然后使用densite_-RANK->densite_-RANK按c.名称顺序按IIFc.值='a',NULL,c.rn划分
这里的技巧是根据条件IIFc.value='a',NULL,c.rn将其设为NULL的顺序
不完全是这样,例如Joe的值是B的两倍,但Row应该保持递增。或者,有没有一种方法可以通过密集排列来实现这一点?此外,我在这里为我的行使用假名称,不需要担心用户行名称。不过还是要谢谢你的提醒!所以在“A”处总是1,然后不管怎样递增,@PAT_The_Whale?混乱,但基于这种逻辑,底部的版本是有效的。它对我有效,@PAT_The_Whale:。为什么我包括DDL和DML。如果不是,那么你就没有告诉我们什么。你已经补充了另一个答案,@PAT_The_Whale。请不要再移动目标柱。你想要什么的逻辑是什么?从你的数据中我可以看到A和Rick是1,A和Joe也是1。怎么会这样?你什么意思?如果你需要它,你可以想象它的价值,就像是法拉利或者其他什么车型。问题已经改变了,这是不可能的。您的数据中没有任何内容可以使用order BY来维护其顺序。表本身是无序的,因此在您的问题中,表中A“B”下方出现的“A”可能位于表中的任何位置。每个值都有一个唯一的ID,这可能吗?我看不出这可能,因为您没有按顺序显示ID,这意味着您需要某种其他类型的顺序—您在其中显示记录的顺序是什么?如果源表中有另一列,如标识,并且您希望该顺序是这样的,则可以跳过cte_添加_简单_顺序,直接使用该顺序。按c.名称顺序按IIFc.值='a',NULL,唯一顺序或列我认为你的方法行不通。它不仅在900行的4,30分钟内非常慢,而且行数有时会从1跳到8,例如,尽管用户只有2个值
2 |B |Joe
2 |B |Joe
2 |B |Joe
3 |B |Joe
WITH
cte_dataset ([value], [name])
AS (SELECT 'A' AS v, 'Rick' AS n
UNION ALL
SELECT 'A' AS v, 'Rick' AS n
UNION ALL
SELECT 'B' AS v, 'Rick' AS n
UNION ALL
SELECT 'C' AS v, 'Rick' AS n
UNION ALL
SELECT 'A' AS v, 'Joe' AS n
UNION ALL
SELECT 'B' AS v, 'Joe' AS n
UNION ALL
SELECT 'B' AS v, 'Joe' AS n)
, cte_add_simple_order
AS (
SELECT
c.value,
c.name,
ROW_NUMBER() OVER (PARTITION BY c.name ORDER BY c.value) AS rn
FROM cte_dataset c
)
SELECT
c.value
, c.name
, DENSE_RANK() OVER (PARTITION BY c.name ORDER BY IIF(c.value = 'a', NULL, c.rn))
FROM cte_add_simple_order c
ORDER BY
c.name DESC
, c.value ;
|value|name|Rank|
|A |Rick|1 |
|A |Rick|1 |
|B |Rick|2 |
|C |Rick|3 |
|A |Joe |1 |
|B |Joe |2 |
|B |Joe |3 |