我正在尝试获取包含在列表中的ID的产品的信息。问题是该列表包含一些单个值和一些范围值:
PX03 - PX069,PX20,PX202,PX25 - PX270,PX250 - PX2509,PX251,PX2511 - PX2513
基本上我正在寻找的是获取包含值和范围的列表或字符串的一些方法,并且结束输出是一个表或列表,它具有单独的范围内的所有值,以便我可以遍历它们。
我有一个存储过程循环遍历主产品表中使用'PX'前缀的所有ID,但该表包含所有ID(即PX 1 - 9999,LX 00001 - 99999),我只想搜索上面列表中包含的内容。我可以单独写出所有id,但是一些范围包含许多值,这将耗费时间。
我的想法是创建一个包含此列表的单独表,其中将有三列:标识列,然后是一列,用于范围的开头和结尾。任何没有范围的项目只有开始和结束范围的相同值,即:
----------------------------------
rownum | range_start | range_end|
----------------------------------
1 PX03 PX069
2 PX20 PX20
3 PX202 PX202
4 PX25 PX25
5 PX250 PX2509
然后使用以下内容填充表格:
SELECT id from product_table
WHERE id BETWEEN listtable.range_start AND listtable.range_end
其中product_table是我的原始表,其中包含产品ID,其信息和listtable是我刚刚创建的新表。这会给我:
id|
---
PX03
PX030
PX031
PX032
PX033
.
.
.
PX067
PX068
PX069
PX20
PX202
PX25
PX250
PX251
等
但我想我需要遍历列表,我不知道该怎么做。任何想法,提示或建议?
更新
使用@asantaballa提供的解决方案创建表后,就像使用内连接一样简单:
SELECT d.id
FROM product_table d
INNER JOIN @RangeTable r
ON d.id BETWEEN r.RangeFrom AND r.RangeTo
答案 0 :(得分:0)
看看这是否适用于有关将字符串转换为表格的部分。
Declare @StrList Varchar(1000) = 'PX03 - PX069, PX20, PX202, PX25 - PX270, PX250 - PX2509, PX251, PX2511 - PX2513'
Declare @RangeTable Table (RangeFrom VarChar(32), RangeTo VarChar(32))
Select @StrList = Replace(@StrList,' ', '') + ','
Declare @StrListItem Varchar(32)
While CHARINDEX(',', @StrList) > 0
Begin
Select @StrListItem = SUBSTRING(@StrList,1,CHARINDEX(',', @StrList) - 1)
Declare
@RangeFrom VarChar(32)
, @RangeTo VarChar(32)
If CHARINDEX('-', @StrListItem) = 0
Begin
Select
@RangeFrom = @StrListItem
, @RangeTo = @StrListItem
End
Else
Begin
Select
@RangeFrom = SUBSTRING(@StrListItem, 1, CHARINDEX('-', @StrListItem) - 1)
, @RangeTo = SUBSTRING(@StrListItem, CHARINDEX('-', @StrListItem) + 1, LEN(@StrListItem) - CHARINDEX('-', @StrListItem))
End
Insert Into @RangeTable (RangeFrom, RangeTo) Values (@RangeFrom, @RangeTo)
Select @StrList = SUBSTRING(@StrList, CHARINDEX(',', @StrList) + 1, LEN(@StrList) - CHARINDEX(',', @StrList))
End
Select * From @RangeTable
答案 1 :(得分:0)
以下是您的string
和product_table
DECLARE @STR VARCHAR(100) = 'PX03 - PX069, PX20, PX202, PX25 - PX270, PX250 - PX2509, PX251, PX2511 - PX2513'
SELECT * INTO #product_table
FROM
(
SELECT 'PX4' PRODID
UNION ALL
SELECT 'PX26'
UNION ALL
SELECT 'PX75'
UNION ALL
SELECT 'PX77'
)TAB
现在创建一个表来保存值
CREATE TABLE #listtable(ROWNUM int IDENTITY(1,1),range_start VARCHAR(100),range_end VARCHAR(100))
现在将拆分值插入表格。
INSERT INTO #listtable
SELECT
ISNULL(PARSENAME(REPLACE(Split.a.value('.', 'VARCHAR(100)'),'-','.'),2),Split.a.value('.', 'VARCHAR(100)')) 'range_start' ,
PARSENAME(REPLACE(Split.a.value('.', 'VARCHAR(100)'),'-','.'),1) 'range_end'
FROM
(
SELECT CAST ('<M>' + REPLACE(@STR, ',', '</M><M>') + '</M>' AS XML) AS Data
) AS A
CROSS APPLY Data.nodes ('/M') AS Split(a)
由于Id是字符串,因此您需要一个从Id中提取数字的函数(由SQL Server之神创建的函数 - Pinal Dave)
CREATE FUNCTION dbo.udf_GetNumeric
(@strAlphaNumeric VARCHAR(256))
RETURNS VARCHAR(256)
AS
BEGIN
DECLARE @intAlpha INT
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric)
BEGIN
WHILE @intAlpha > 0
BEGIN
SET @strAlphaNumeric = STUFF(@strAlphaNumeric, @intAlpha, 1, '' )
SET @intAlpha = PATINDEX('%[^0-9]%', @strAlphaNumeric )
END
END
RETURN ISNULL(@strAlphaNumeric,0)
END
首先请注意,如果您提供PX1,PX2,PX3,PX4
,我们将无法获得id BETWEEN listtable.range_start AND listtable.range_end
因为varchar
类型而非numbers
。因此,我们需要从每个PX
中提取数字并获取它们之间的值并附加PX
。
以下是过滤product_table
中listtable
;WITH CTE AS
(
SELECT ROWNUM,CAST(dbo.udf_GetNumeric(range_start)AS INT) NUMBERS,
CAST(dbo.udf_GetNumeric(range_end)AS INT) RTO1
FROM #listtable
UNION ALL
SELECT T.ROWNUM,NUMBERS+1,RTO1
FROM #listtable T
JOIN CTE ON CTE.ROWNUM = T.ROWNUM
WHERE NUMBERS < RTO1
)
SELECT PRODID IDS--,ROWNUM,NUMBERS NUMS,'PX'+CAST(NUMBERS AS VARCHAR(10)) IDS2
FROM CTE
JOIN #product_table ON PRODID='PX'+CAST(NUMBERS AS VARCHAR(10))
ORDER BY NUMBERS
option (MaxRecursion 0)