2013-05-21 68 views
1

我有一些棘手的情況。我有一列在表中的許多行中包含一組以管爲分隔符的數字。例如:SQL中返回包含相同值/字符的不同行

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

我想實現的是返回數字在輸出中只出現一次的行。

理想情況下,我想嘗試使用SQL執行此操作,而不必在Web應用程序級別執行檢查。執行DISTINCT並不能達到我想要的效果。

所需的輸出將是:

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

我會理解,如果任何人都可以引導我在正確的方向。

謝謝。

+0

,你會想到什麼作爲輸出?只有10? 3,8,10和12?其他? –

+0

@sbhomra:給定樣本輸入的期望輸出是多少? –

+0

@RaviSingh我已經用期望的輸出更新了我的問題。 – sbhomra

回答

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 
+0

偉大的解決方案。但只是爲了我的SQL知識,你能解釋一行:「CAST(Split.a.value('。','VARCHAR(100)')AS INT)」。爲什麼Split.a.value需要在整個停止狀態下分割?只是好奇。 :-) – sbhomra

0

不能沒有遞歸管理:(像這樣的東西可以做的trich

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 

沒能成功運行,但它應該做的伎倆,?只需更換和正確的信息

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

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 != '' 
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 
相關問題