它看起来像主的混乱是由你的SQL语句的问题,你只需GROUP BY LASTNAME, HOUSENO
的开始引起落实。
如果你想要一个简单的分组,你的查询将是正确的。但是,那么您向我们展示了一个具有预期结果的更详细的示例数据,并且很明显,您不仅需要一个分组(它不关心数据中行的顺序),而且希望根据它们对行进行分组序列。
这是一个经典问题gaps-and-islands
。在SQL Server 2008中,可以使用对ROW_NUMBER
函数的少量调用来完成。
的样本数据
DECLARE @T TABLE
(id int PRIMARY KEY
,FirstName nvarchar(50)
,LastName nvarchar(50)
,HouseNo nvarchar(50)
,MyCount int
,CountId int);
INSERT INTO @T (id, FirstName, LastName, HouseNo) VALUES
(1 , 'Imran ', 'Khan ', '1-1'),
(2 , 'Waseem', 'Khan ', '1-1'),
(3 , 'Rihan ', 'Khan ', '1-1'),
(4 , 'Moiz ', 'Shaikh', '1-2'),
(5 , 'Zbair ', 'Shaikh', '1-2'),
(6 , 'Sultan', 'Shaikh', '1-2'),
(7 , 'Zaid ', 'Khan ', NULL),
(10, 'Parvez', 'Patel ', '1-3'),
(11, 'Ahmed ', 'Patel ', '1-3'),
(12, 'Rahat ', 'Syed ', '1-4'),
(13, 'Talha ', 'Khan ', NULL),
(14, 'Zia ', 'Khan ', NULL),
(15, 'Arshad', 'Patel ', '1-3'),
(16, 'Samad ', 'Patel ', '1-3'),
(17, 'Raees ', 'Syed ', '1-4'),
(18, 'Azmat ', 'Khan ', NULL),
(19, 'Imran ', 'Khan ', NULL);
SELECT查询
WITH
CTE_RN
AS
(
SELECT
id
,FirstName
,LastName
,HouseNo
,MyCount
,CountId
,ROW_NUMBER() OVER (PARTITION BY LastName, HouseNo ORDER BY ID) AS rn1
,ROW_NUMBER() OVER (ORDER BY ID) AS rn2
FROM @T AS T
)
,CTE_GRoups
AS
(
SELECT
id
,FirstName
,LastName
,HouseNo
,MyCount
,CountId
,rn1
,rn2
,rn2-rn1 AS GroupNumber
,COUNT(ID) OVER (PARTITION BY LastName, HouseNo, rn2-rn1) AS NewMyCount
,MIN(ID) OVER (PARTITION BY LastName, HouseNo, rn2-rn1) AS GroupMinID
FROM CTE_RN
)
SELECT
id
,FirstName
,LastName
,HouseNo
,rn1
,rn2
,GroupNumber
,NewMyCount
,GroupMinID
,DENSE_RANK() OVER (ORDER BY GroupMinID) AS NewCountId
FROM CTE_GRoups
ORDER BY ID;
结果
+----+-----------+----------+---------+-----+-----+-------------+------------+------------+------------+
| id | FirstName | LastName | HouseNo | rn1 | rn2 | GroupNumber | NewMyCount | GroupMinID | NewCountId |
+----+-----------+----------+---------+-----+-----+-------------+------------+------------+------------+
| 1 | Imran | Khan | 1-1 | 1 | 1 | 0 | 3 | 1 | 1 |
| 2 | Waseem | Khan | 1-1 | 2 | 2 | 0 | 3 | 1 | 1 |
| 3 | Rihan | Khan | 1-1 | 3 | 3 | 0 | 3 | 1 | 1 |
| 4 | Moiz | Shaikh | 1-2 | 1 | 4 | 3 | 3 | 4 | 2 |
| 5 | Zbair | Shaikh | 1-2 | 2 | 5 | 3 | 3 | 4 | 2 |
| 6 | Sultan | Shaikh | 1-2 | 3 | 6 | 3 | 3 | 4 | 2 |
| 7 | Zaid | Khan | NULL | 1 | 7 | 6 | 1 | 7 | 3 |
| 10 | Parvez | Patel | 1-3 | 1 | 8 | 7 | 2 | 10 | 4 |
| 11 | Ahmed | Patel | 1-3 | 2 | 9 | 7 | 2 | 10 | 4 |
| 12 | Rahat | Syed | 1-4 | 1 | 10 | 9 | 1 | 12 | 5 |
| 13 | Talha | Khan | NULL | 2 | 11 | 9 | 2 | 13 | 6 |
| 14 | Zia | Khan | NULL | 3 | 12 | 9 | 2 | 13 | 6 |
| 15 | Arshad | Patel | 1-3 | 3 | 13 | 10 | 2 | 15 | 7 |
| 16 | Samad | Patel | 1-3 | 4 | 14 | 10 | 2 | 15 | 7 |
| 17 | Raees | Syed | 1-4 | 2 | 15 | 13 | 1 | 17 | 8 |
| 18 | Azmat | Khan | NULL | 4 | 16 | 12 | 2 | 18 | 9 |
| 19 | Imran | Khan | NULL | 5 | 17 | 12 | 2 | 18 | 9 |
+----+-----------+----------+---------+-----+-----+-------------+------------+------------+------------+
在这里,我包括在结果所有中间步骤,所以你可以看到它是如何工作的。主要部分是两套ROW_NUMBER
s。 rn1
序列重新启动为每个LastName, HouseNo
。它由LastName, HouseNo
分区。 rn2
是一个简单的增加序列没有差距。我们需要它,因为原始ID
定义了顺序,但可能有空白。
然后我们减去这两个序列,差异给我们GroupNumber
。
计算组中元素的数量很简单COUNT
,这给了我们NewMyCount
。
用两个步骤完成无间隙序列号的枚举。起初MIN
给出了一个组的标识符,然后DENSE_RANK
生成一个没有间隙的序列NewCountId
。
如果你想真正与计算NewMyCount
和NewCountId
更新原来的表,很容易打开SELECT
上面的查询到UPDATE
查询:
UPDATE查询
WITH
CTE_RN
AS
(
SELECT
id
,FirstName
,LastName
,HouseNo
,MyCount
,CountId
,ROW_NUMBER() OVER (PARTITION BY LastName, HouseNo ORDER BY ID) AS rn1
,ROW_NUMBER() OVER (ORDER BY ID) AS rn2
FROM @T AS T
)
,CTE_GRoups
AS
(
SELECT
id
,FirstName
,LastName
,HouseNo
,MyCount
,CountId
,rn1
,rn2
,rn2-rn1 AS GroupNumber
,COUNT(ID) OVER (PARTITION BY LastName, HouseNo, rn2-rn1) AS NewMyCount
,MIN(ID) OVER (PARTITION BY LastName, HouseNo, rn2-rn1) AS GroupMinID
FROM CTE_RN
)
,CTE_Update
AS
(
SELECT
id
,FirstName
,LastName
,HouseNo
,MyCount
,CountId
,rn1
,rn2
,GroupNumber
,NewMyCount
,GroupMinID
,DENSE_RANK() OVER (ORDER BY GroupMinID) AS NewCountId
FROM CTE_GRoups
)
UPDATE CTE_Update
SET
MyCount = NewMyCount
,CountId = NewCountId
;
结果
SELECT *
FROM @T
ORDER BY ID;
+----+-----------+----------+---------+---------+---------+
| id | FirstName | LastName | HouseNo | MyCount | CountId |
+----+-----------+----------+---------+---------+---------+
| 1 | Imran | Khan | 1-1 | 3 | 1 |
| 2 | Waseem | Khan | 1-1 | 3 | 1 |
| 3 | Rihan | Khan | 1-1 | 3 | 1 |
| 4 | Moiz | Shaikh | 1-2 | 3 | 2 |
| 5 | Zbair | Shaikh | 1-2 | 3 | 2 |
| 6 | Sultan | Shaikh | 1-2 | 3 | 2 |
| 7 | Zaid | Khan | NULL | 1 | 3 |
| 10 | Parvez | Patel | 1-3 | 2 | 4 |
| 11 | Ahmed | Patel | 1-3 | 2 | 4 |
| 12 | Rahat | Syed | 1-4 | 1 | 5 |
| 13 | Talha | Khan | NULL | 2 | 6 |
| 14 | Zia | Khan | NULL | 2 | 6 |
| 15 | Arshad | Patel | 1-3 | 2 | 7 |
| 16 | Samad | Patel | 1-3 | 2 | 7 |
| 17 | Raees | Syed | 1-4 | 1 | 8 |
| 18 | Azmat | Khan | NULL | 2 | 9 |
| 19 | Imran | Khan | NULL | 2 | 9 |
+----+-----------+----------+---------+---------+---------+
您由LASTNAME,HOUSENO分组。 A/NULL和K/NULL显然是两个不同的组,所以我没有看到你的查询如何给你一个5的合并计数。请问'SELECT LASTNAME,HOUSENO,COUNT(ID)'而不是'SELECT COUNT(ID)',以查看哪个组获得5的计数? –
我刚刚检查过它。您的查询 - 除了错字GRUOP/GROUP之外,*不会*返回5,而是分别返回3和2,就像您想要的一样,并且我确信它会。这里是SQL小提琴:http://sqlfiddle.com/#!6/c536b/2。所以你可以在我看来完全删除这个问题。 –