从每条记录的逗号分隔值中选择 Min/Max

Selecting Min/Max from Comma Separated Values against each record

考虑以下 table 及其记录

create table dbo.test
(
id  numeric(4),
vals    nvarchar(1000)
);

insert into dbo.test values (1,'1,2,3,4,5');
insert into dbo.test values (2,'6,7,8,9,0');
insert into dbo.test values (3,'11,54,76,23');

我将使用下面的函数来拆分 CSV,您可以使用任何方法来帮助 select 语法

CREATE FUNCTION [aml].[Split](@String varchar(8000), @Delimiter char(1))     
returns @temptable TABLE (items varchar(8000))     
as     
begin     
declare @idx int     
declare @slice varchar(8000)     

select @idx = 1     
    if len(@String)<1 or @String is null  return     

while @idx!= 0     
begin     
    set @idx = charindex(@Delimiter,@String)     
    if @idx!=0     
        set @slice = left(@String,@idx - 1)     
    else     
        set @slice = @String     

    if(len(@slice)>0)
        insert into @temptable(Items) values(@slice)     

    set @String = right(@String,len(@String) - @idx)     
    if len(@String) = 0 break     
end 
return     
end

我想 select idmaxmin 来自 vals 的值对每条记录。

更新 虽然我在 SQL Server 2008 上编写查询,但我需要支持 SQL Server 2005 及更高版本

您可以 CROSS APPLY 到函数投影的 table,然后对每组 id 应用普通聚合函数:

SELECT t.id, MIN(CAST(x.items AS INT)) AS MinItem, MAX(CAST(x.items AS INT)) AS MaxItem
FROM dbo.test t 
     CROSS APPLY dbo.Split(t.vals, ',') x
GROUP BY t.id;

(Edit - 因为这些看起来是整数,所以您需要在应用 MIN / MAX 聚合之前进行转换,否则您将得到字母数字排序)

SqlFiddle example here

另一种选择是在对其应用查询之前将逗号分隔列表保存在规范化 table 结构中 - 在 RDBMS 中存储非规范化数据没有用:)

没有功能,只是普通sql:

SELECT t.id,  
       Max(Split.a.value('.', 'VARCHAR(100)')) AS MaxVal,
       Min(Split.a.value('.', 'VARCHAR(100)')) AS MinVal
 FROM
 (
     SELECT id,  
         CAST ('<M>' + REPLACE(vals, ',', '</M><M>') + '</M>' AS XML) AS Data  
     FROM  test
 ) AS t CROSS APPLY Data.nodes ('/M') AS Split(a)
 group by t.id

Fiddle http://sqlfiddle.com/#!3/22321/6

select A.id,(select max(item) from dbo.Split(A.vals,',')) as maxvalue,(select 来自 dbo.Split(A.vals,',')) 的 min(item) 作为来自测试 A

的最小值

为 fplit 创建函数 创建函数拆分 ( @InputString VARCHAR(8000), @Delimiter VARCHAR(50) )

RETURNS @Items TABLE ( 项目 VARCHAR(8000) )

作为 开始 IF @Delimiter = ' ' 开始 SET @Delimiter = ',' SET @InputString = REPLACE(@InputString, ' ', @Delimiter) 结束

  IF (@Delimiter IS NULL OR @Delimiter = '')
        SET @Delimiter = ','

--IN​​SERT INTO @Items VALUES (@Delimiter) -- 诊断 --INSERT INTO @Items VALUES (@InputString) -- 诊断

  DECLARE @Item                 VARCHAR(8000)
  DECLARE @ItemList       VARCHAR(8000)
  DECLARE @DelimIndex     INT

  SET @ItemList = @InputString
  SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
  WHILE (@DelimIndex != 0)
  BEGIN
        SET @Item = SUBSTRING(@ItemList, 0, @DelimIndex)
        INSERT INTO @Items VALUES (@Item)

        -- Set @ItemList = @ItemList minus one less item
        SET @ItemList = SUBSTRING(@ItemList, @DelimIndex+1, LEN(@ItemList)-@DelimIndex)
        SET @DelimIndex = CHARINDEX(@Delimiter, @ItemList, 0)
  END -- End WHILE

  IF @Item IS NOT NULL -- At least one delimiter was encountered in @InputString
  BEGIN
        SET @Item = @ItemList
        INSERT INTO @Items VALUES (@Item)
  END

  -- No delimiters were encountered in @InputString, so just return @InputString
  ELSE INSERT INTO @Items VALUES (@InputString)

  RETURN

END -- 结束函数 去