从每个记录中选择逗号分隔值的最小值/最大值

时间:2015-06-04 04:21:01

标签: sql sql-server sql-server-2005

考虑下表及其记录

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

我想从id中为每条记录选择maxmin以及vals值。

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

3 个答案:

答案 0 :(得分:4)

您可以CROSS APPLY到函数投影的表格,然后在每个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;

修改 - 由于这些似乎是整数,因此您需要在应用MIN / MAX聚合之前进行投射,否则您将获得字母数字排序)

SqlFiddle example here

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

答案 1 :(得分:3)

没有功能,只需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

小提琴http://sqlfiddle.com/#!3/22321/6

答案 2 :(得分:0)

选择A.id,(从dbo.Split中选择max(item)(A.vals,&#39;,&#39;))作为maxvalue,(从dbo.Split中选择min(item)(A。 vals,&#39;,#);)作为测试A的最小值

为fplit创建函数 创造功能分裂(       @InputString VARCHAR(8000),       @Delimiter VARCHAR(50) )

RETURNS @Items TABLE(       物品VARCHAR(8000) )

AS 开始       如果@Delimiter =&#39; &#39;       开始             SET @Delimiter =&#39;,&#39;             SET @InputString = REPLACE(@InputString,&#39;&#39;,@ Delimiter)       END

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

- INSERT 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

结束 - 结束功能 GO