返回在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需要在句号上拆分?只是好奇-