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

返回在SQL中包含相同值/字符的不同行,sql,sql-server,Sql,Sql Server,我的处境有点棘手。我有一个列,其中包含一组以管道分隔的数字,这些数字位于表中的许多行中。例如: Courses ------------------- 1|2 1|2|3 1|2|8 10 11 11|12 我想要实现的是返回数字在输出中只出现一次的行 理想情况下,我希望尝试使用SQL执行此操作,而不必在web应用程序级别执行检查。执行一项独特的计划并不能实现我想要的 所需的输出将是: Courses ------------------- 1 2 3 8 10 11 12 如果有人能为我指

我的处境有点棘手。我有一个列,其中包含一组以管道分隔的数字,这些数字位于表中的许多行中。例如:

Courses
-------------------
1|2
1|2|3
1|2|8
10
11
11|12
我想要实现的是返回数字在输出中只出现一次的行

理想情况下,我希望尝试使用SQL执行此操作,而不必在web应用程序级别执行检查。执行一项独特的计划并不能实现我想要的

所需的输出将是:

Courses
-------------------
1
2
3
8
10
11
12
如果有人能为我指引正确的方向,我将不胜感激

谢谢。

请尝试:

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
请尝试:

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

如果没有递归就无法管理:类似这样的东西可以完成这个任务吗

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即可。

没有递归就无法管理:像这样的东西可以完成任务吗

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替换为正确的信息即可

一种方法是使用递归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

SQLFIDLE。

一种方法是使用递归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。

试试这个-

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 != ''
试试这个-

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 != ''
试试这个:

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
试试这个:

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

您希望得到什么样的输出?只有10个?3、8、10和12?其他?@sbhomra:给定样本输入的期望输出是什么?@RaviSingh我已经用期望输出更新了我的问题。你期望输出是什么?只有10个?3、8、10和12?其他?@sbhomra:给定样本输入的期望输出是什么?@RaviSingh我已经用期望输出更新了我的问题。很好的解决方案。但就我的SQL知识而言,您能解释一下行:CASTSplit.a.value'.'和'VARCHAR100'是INT吗?为什么Split.a.value需要在句号上拆分?只是好奇-很好的解决方案。但就我的SQL知识而言,您能解释一下行:CASTSplit.a.value'.'和'VARCHAR100'是INT吗?为什么Split.a.value需要在句号上拆分?只是好奇-