gpt4 book ai didi

sql-server - 从 MSSQL 中的表中获取数字范围

转载 作者:行者123 更新时间:2023-12-03 16:25:47 26 4
gpt4 key购买 nike

我在 SQL 2008R2 中有一个表:

    ID  |  PinAddress-------------------------------------   1  |   1   1  |   2   1  |   3   1  |   4   1  |   5   1  |   6   1  |   16   1  |   31   2  |   55   2  |   56   2  |   57   2  |   81   2  |   82   2  |   83   2  |   84   3  |   101   3  |   102   3  |   103   3  |   107   3  |   108   3  |   109

What I want is when I search for ID = 1,I want result like

1-6,16,31

When I search for ID = 2,I want result like

55-57,81-84

When I search for ID = 3,I want result like

101-103,107-109

You can use below script to create table and data:

CREATE TABLE PinAddress(ID INT,PinAddress INT)
INSERT INTO PinAddress values(1,1)
INSERT INTO PinAddress values(1,2)
INSERT INTO PinAddress values(1,3)
INSERT INTO PinAddress values(1,4)
INSERT INTO PinAddress values(1,5)
INSERT INTO PinAddress values(1,6)
INSERT INTO PinAddress values(1,16)
INSERT INTO PinAddress values(1,31)
INSERT INTO PinAddress values(2,55)
INSERT INTO PinAddress values(2,56)
INSERT INTO PinAddress values(2,57)
INSERT INTO PinAddress values(2,81)
INSERT INTO PinAddress values(2,82)
INSERT INTO PinAddress values(2,83)
INSERT INTO PinAddress values(2,84)
INSERT INTO PinAddress values(3,101)
INSERT INTO PinAddress values(3,102)
INSERT INTO PinAddress values(3,103)
INSERT INTO PinAddress values(3,107)
INSERT INTO PinAddress values(3,108)
INSERT INTO PinAddress values(3,109)

谢谢

最佳答案

这是一个 gaps and islands problem ,关键是识别您的连续范围,这是使用 ROW_NUMBER() 完成的。所以对于 ID 3,你有:

ID  PinAddress  RowNumber
---------------------------
3 101 1
3 102 2
3 103 3
3 107 4
3 108 5
3 109 6

从引脚地址中减去行号将为每个连续范围提供一个常数值:

ID  PinAddress  RowNumber   (PinAddress - RowNumber)
---------------------------------------------------
3 101 1 100
3 102 2 100
3 103 3 100
---------------------------------------------------
3 107 4 103
3 108 5 103
3 109 6 103

到目前为止的查询很简单:

SELECT  ID,
PinAddress,
GroupingSet = PinAddress - ROW_NUMBER() OVER(PARTITION BY ID ORDER BY PinAddress)
FROM dbo.PinAddress;

然后您可以按常量值和 ID 进行分组,并使用 MINMAX 获取每个范围的开始和结束:

WITH RankedData AS
( SELECT ID,
PinAddress,
GroupingSet = PinAddress - ROW_NUMBER() OVER(PARTITION BY ID ORDER BY PinAddress)
FROM PinAddress
)
SELECT ID,
RangeStart = MIN(PinAddress),
RangeEnd = MAX(PinAddress),
RangeText = CONVERT(VARCHAR(10), MIN(PinAddress)) +
CASE WHEN MIN(PinAddress) = MAX(PinAddress) THEN ''
ELSE ' - ' + CONVERT(VARCHAR(10), MAX(PinAddress))
END
FROM RankedData
GROUP BY ID, GroupingSet;

其中,对于 ID 3 给出:

ID  RangeStart  RangeEnd    RangeText
-----------------------------------------
3 101 103 101 - 103
3 107 109 107 - 109

最后,您需要将 RangeText 值连接成一行,这可以使用 SQL Server's XML Extensions 来完成.

WITH RankedData AS
( SELECT ID,
PinAddress,
GroupingSet = PinAddress - ROW_NUMBER() OVER(PARTITION BY ID ORDER BY PinAddress)
FROM PinAddress
)
SELECT p.ID,
Ranges = STUFF((SELECT ', ' + CONVERT(VARCHAR(10), MIN(PinAddress)) +
CASE WHEN MIN(PinAddress) = MAX(PinAddress) THEN ''
ELSE ' - ' + CONVERT(VARCHAR(10), MAX(PinAddress))
END
FROM RankedData AS rd
WHERE rd.ID = p.ID
GROUP BY ID, GroupingSet
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 2, '')
FROM (SELECT DISTINCT ID FROM PinAddress) AS p;

给出:

ID      Ranges
------------------------------
1 1 - 6, 16 - 16, 31 - 31
2 55 - 57, 81 - 84
3 101 - 103, 107 - 109

关于sql-server - 从 MSSQL 中的表中获取数字范围,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30801547/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com