1

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

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

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

理想情况下,我想尝试使用 SQL 来执行此操作,而不必在 Web 应用程序级别执行检查。执行 DISTINCT 并不能达到我想要的效果。

所需的输出将是:

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

如果有人能指导我正确的方向,我将不胜感激。

谢谢。

4

5 回答 5

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
于 2013-05-21T09:42:04.603 回答
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 != ''
于 2013-05-21T10:02:16.423 回答
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
于 2013-05-21T10:13:57.030 回答
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

没有让它运行,但它应该可以解决问题,只需将 and 替换为正确的信息

于 2013-05-21T09:42:22.583 回答
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在这里

于 2013-05-21T09:56:45.547 回答