返回SQL中包含相同值/字符的不同行

时间:2013-05-21 09:31:56

标签: sql sql-server

我有点棘手的情况。我有一个列,其中包含表中许多行中以管道分隔的数字集。例如:

Courses
-------------------
1|2
1|2|3
1|2|8
10
11
11|12

我想要实现的是返回数字仅在输出中出现一次的行。

理想情况下,我想尝试使用SQL执行此操作,而不是必须在Web应用程序级别执行检查。进行DISTINCT并没有实现我的目标。

所需的输出是:

Courses
-------------------
1
2
3
8
10
11
12

如果有人能引导我朝着正确的方向前进,我将不胜感激。

感谢。

5 个答案:

答案 0 :(得分:3)

请尝试:

declare @tbl as table(Courses nvarchar(max))
insert into @tbl values
('1|2'),
('1|2|3'),
('1|2|8'),
('10'),
('11'),
('11|12')

select * from @tbl

SELECT 
     DISTINCT CAST(Split.a.value('.', 'VARCHAR(100)') AS INT) AS CVS  
FROM  
(
    SELECT CAST ('<M>' + REPLACE(Courses, '|', '</M><M>') + '</M>' AS XML) AS CVS  
    FROM  @tbl 
) AS A CROSS APPLY CVS.nodes ('/M') AS Split(a)
ORDER BY 1

答案 1 :(得分:1)

试试这个 -

SET NOCOUNT ON;

DECLARE @temp TABLE
(
      string VARCHAR(500)
)

DECLARE @Separator CHAR(1)
SELECT @Separator = '|'

INSERT INTO @temp (string)
VALUES 
    ('1|2'),
    ('1|2|3'),
    ('1|2|8'),
    ('10'),
    ('11'),
    ('11|12')

-- 1. XML

SELECT p.value('(./s)[1]', 'VARCHAR(500)')
FROM (
    SELECT field = CAST('<r><s>' + REPLACE(t.string, @Separator, '</s></r><r><s>') + '</s></r>' AS XML) 
    FROM @temp t
) d
CROSS APPLY field.nodes('/r') t(p)

-- 2. CTE

;WITH a AS
(
    SELECT 
          start_pos = 1
        , end_pos = CHARINDEX(@Separator, t.string)
        , t.string
    FROM @temp t

    UNION ALL

    SELECT 
          end_pos + 1
        , CHARINDEX(@Separator, string, end_pos + 1)
        , string
    FROM a
    WHERE end_pos > 0
)
SELECT d.name 
FROM (
    SELECT 
          name = SUBSTRING(
              string
            , start_pos
            , ABS(end_pos - start_pos)
        ) 
    FROM a
) d
WHERE d.name != ''

答案 2 :(得分:1)

试试这个:

create table course (courses varchar(100))

insert into course values('1|2')
insert into course values('1|2|3')
insert into course values('1|2|8')
insert into course values('10')
insert into course values('11')
insert into course values('11|12')

Declare @col varchar(200)

SELECT
@col=(
        SELECT DISTINCT  c.courses + '|'
        FROM course c

        FOR XML PATH('')
      );




select * from course

;with demo as(


select cast(substring(@col,1,charindex('|',@col,1)-1) AS INT) cou,charindex('|',@col,1) pos

  union all 
  select cast(substring(@col,pos+1,charindex('|',@col,pos+1)-pos-1)AS INT) cou,charindex('|',@col,pos+1) pos
  from demo where pos<LEN(@col))
select distinct cou from demo

答案 3 :(得分:0)

没有递归就无法管理:(像这样的东西可以做特里奇?

WITH splitNum(num, r)
AS
(
  SELECT
   SUBSTRING(<field>,1, CHARINDEX('|', <field>)-1) num,
   SUBSTRING(<field>,CHARINDEX('|', <field>)+1, len(<field>)) r
  FROM <yourtable> as a
  UNION ALL
  SELECT
    SUBSTRING(r,1, CHARINDEX('|', r)-1) num,
    SUBSTRING(r,CHARINDEX('|', r)+1, len(r)) r
  FROM <yourtable> b
  WHERE CHARINDEX('|', r) > 0
  inner join splitNum as c on <whatevertheprimarykeyis>
 )
 SELECT distinct num FROM splitNum

没有让它运行,但它应该成功,只需用正确的信息替换

答案 4 :(得分:0)

一种方法是使用递归CTE:

with cte as
(select cast(case charindex('|',courses) when 0 then courses
                  else left(courses,charindex('|',courses)-1) end as int) course, 
        case charindex('|',courses) when 0 then ''
             else right(courses,len(courses)-charindex('|',courses)) end courses 
 from courses
 union all
 select cast(case charindex('|',courses) when 0 then courses
                  else left(courses,charindex('|',courses)-1) end as int) course, 
        case charindex('|',courses) when 0 then ''
             else right(courses,len(courses)-charindex('|',courses)) end courses 
 from cte
 where len(courses)>0)
 select distinct course from cte

SQLFiddle here