列中的字符串在MSSQL中选择查询循环

时间:2018-02-19 09:27:56

标签: sql sql-server

我的列包含字符:

TABLE1
======
id  | divs
----------
11  | A
12  | AB
13  | C
14  | E
15  | BDE
16  | F

每个char代表不同的分区,第二个表是:

TABLE2
======
id  | div | TABLE1_id | report
------------------------------
21  | A   | 11        | "Lorem ipsum 1"
22  | B   | 12        | "Lorem ipsum 2"
23  | C   | 13        | "Lorem ipsum 3"
24  | A   | 12        | "Lorem ipsum 4"
25  | B   | 15        | "Lorem ipsum 5"
26  | F   | 16        | "Lorem ipsum 6"

最终报告是:

Reports
=======
TABLE1_id | TABLE2_id | div | report
------------------------------------
11        | 21        | A   | "Lorem ipsum 1"
12        | 24        | A   | "Lorem ipsum 4"
12        | 22        | B   | "Lorem ipsum 2"
13        | 23        | C   | "Lorem ipsum 3"
14        | NULL      | E   | NULL
15        | 25        | B   | "Lorem ipsum 5"
15        | NULL      | D   | NULL
15        | NULL      | E   | NULL
16        | 26        | F   | "Lorem ipsum 6"

字数限制为5:" ABCDE",

我尝试了很多SQL查询,但显然我遗漏了一些东西,并且不知道一些重要的命令...

如何在MSSQL中生成该报告?

5 个答案:

答案 0 :(得分:3)

通常你需要一个计数表。由于您的字符串有限,您可以使用自己生成的数字

declare @t1 table (
    id  int
    , divs varchar(5)
)
insert into @t1
values 
    (11, 'A')
    ,(12, 'AB')
    ,(13, 'C')
    ,(14, 'E')
    ,(15, 'BDE')
    ,(16, 'F')

declare @t2 table (
    id int
    , div varchar(5)
    , TABLE1_id int
    , report varchar(200)
)

insert into @t2
values
(21, 'A', 11, '"Lorem ipsum 1"')
,(22, 'B', 12, '"Lorem ipsum 2"')
,(23, 'C', 13, '"Lorem ipsum 3"')
,(24, 'A', 12, '"Lorem ipsum 4"')
,(25, 'B', 15, '"Lorem ipsum 5"')
,(26, 'F', 16, '"Lorem ipsum 6"')

select
    t.id, z.id, substring(t.divs, q.n, 1), z.report
from
    @t1 t
    join (values (1), (2), (3), (4), (5)) q(n) on len(t.divs) >= q.n
    left join @t2 z on substring(t.divs, q.n, 1) = z.div and t.id = z.TABLE1_id

答案 1 :(得分:2)

您可以使用2016年提供的string_split功能

这样做
declare @myt table (id int, divs nvarchar(50)
)
insert into @myt

values

(11  ,'A'  ),
(12  ,'AB' ),
(13  ,'C'  ),
(14  ,'E'  ),
(15  ,'BDE'),
(16  ,'F'  )

declare @myt2 table (id int,div nvarchar(50),table1_id int, report nvarchar(50))
insert into @myt2

values


(21  ,'A',11,'"Lorem ipsum 1"'),
(22  ,'B',12,'"Lorem ipsum 2"'),
(23  ,'C',13,'"Lorem ipsum 3"'),
(24  ,'A',12,'"Lorem ipsum 4"'),
(25  ,'B',15,'"Lorem ipsum 5"'),
(26  ,'F',16,'"Lorem ipsum 6"')


select x.id,b.id as Table1_id,[value],report from (
select *,substring(divs,1,1)+','+substring(divs,2,1)+','+substring(divs,3,1)+','+substring(divs,4,1)+','+substring(divs,5,1) as divs2 from @myt
) x
cross apply string_split(divs2,',')
left join @myt2 b on x.id = b.table1_id and b.div = [value]
where value!= ''

答案 2 :(得分:2)

由于OP尚未针对他们尝试过的请求发布回复,我故意将此不完整。向我们展示你以前尝试过的东西是一种很好的做法;我们不是为你做的工作。

OP,您需要向此正确添加SELECT子句,将相关列添加到CROSS APPLY并完成CREATE TABLE #Table1 (id tinyint, divs varchar(5)); CREATE TABLE #Table2 (id tinyint, div char(1), Table1_id tinyint, report varchar(50)); INSERT INTO #Table1 VALUES (11,'A'), (12,'AB'), (13,'C'), (14,'E'), (15,'BDE'), (16,'F'); INSERT INTO #Table2 VALUES (21,'A',11,'"Lorem ipsum 1"'), (22,'B',12,'"Lorem ipsum 2"'), (23,'C',13,'"Lorem ipsum 3"'), (24,'A',12,'"Lorem ipsum 4"'), (25,'B',15,'"Lorem ipsum 5"'), (26,'F',16,'"Lorem ipsum 6"'); GO SELECT * FROM #Table1 T1 CROSS APPLY (VALUES(SUBSTRING(T1.divs,1,1)),(SUBSTRING(T1.divs,2,1))) D(div) LEFT JOIN #Table2 T2 ON T1.id = T2.Table1_id AND D.div = T2.div; GO DROP TABLE #Table1; DROP TABLE #Table2; (它只能处理目前前2个div)。如果您不明白,请询问:

min

答案 3 :(得分:1)

其他选项是使用 admin-name cte方法,该方法不仅限于5个字符

recursive

结果:

;with cte as
(
    select id, divs, len(divs) pos, 1 start 
    from table1
), cte1 as
(
    select id, divs, pos, start, '' splitdivs from cte
    union all
    select id, divs, pos, start+1, substring(divs, start+1, 1) splitdivs
    from cte1
    where pos > start
)
select c.id TABLE1_id, t2.id TABLE2_id, 
       (case when splitdivs = '' then substring(divs, 1,1) else splitdivs end) div, 
       t2.report 
from cte1 c
left join table2 t2 on t2.TABLE1_id = c.id and 
          t2.div = (case when splitdivs = '' then substring(divs, 1,1) else splitdivs end)
order by 1

答案 4 :(得分:1)

另一种解决方案:

免责声明我没有看到Uzi已经发布了类似的解决方案

    DECLARE @Tbl TABLE (Id int , Divs nvarchar(5))
    INSERT INTO @Tbl (Id, Divs)
    SELECT 11  , 'A'
    UNION ALL 
    SELECT 12  , 'AB'
    UNION ALL 
    SELECT 13  , 'C'
    UNION ALL 
    SELECT 14  , 'E'
    UNION ALL 
    SELECT 15  , 'BDE'
    UNION ALL 
    SELECT 16  , 'F'


    DECLARE @Tbl2 TABLE (Id INT , Div NVARCHAR(1), Table1_Id INT , Report nvarchar(20))
    INSERT INTO @Tbl2 (Id, Div , Table1_Id , Report)
    SELECT 21  , 'A'   , 11        , '"Lorem ipsum 1"'
    UNION ALL
    SELECT 22  , 'B'   , 12        , '"Lorem ipsum 2"'
    UNION ALL
    SELECT 23  , 'C'   , 13        , '"Lorem ipsum 3"'
    UNION ALL
    SELECT 24  , 'A'   , 12        , '"Lorem ipsum 4"'
    UNION ALL
    SELECT 25  , 'B'   , 15        , '"Lorem ipsum 5"'
    UNION ALL
    SELECT 26  , 'F'   , 16        , '"Lorem ipsum 6"'



    ;WITH nums (n)
    AS 
    (
    SELECT ROW_NUMBER () OVER (ORDER BY (SELECT NULL))  
    FROM (VALUES (0),(0),(0),(0),(0)) a(n)
    )
    , Tbl1 as 
    (
    SELECT Id , SUBSTRING(Divs,n,1) Div
    FROM @Tbl t
    CROSS APPLY 
        (
        VALUES (LEN(Divs))
        ) X(ChrLen)
    CROSS JOIN nums n
    WHERE n <= ChrLen
    )

    SELECT t1.Id Table1_Id , t2.Id Table2_Id ,t1.Div , t2.Report
    FROM Tbl1 T1
    LEFT JOIN @Tbl2  T2
    ON T2 .Div = T1.Div
    AND t1.Id = T2.Table1_Id
相关问题