Query for comma-separated ids to comma-separated values

后端 未结 5 1532
终归单人心
终归单人心 2021-01-03 03:16

I have 2 tables

Departments

ID  Dept
---------
1   HR
2   Accts
3   IT

Employee

I         


        
相关标签:
5条回答
  • 2021-01-03 03:30

    Looking beyond how you're storing your data, let me try to help you out.

    Well, you're asking a lot of questions here. First, to split the data, you can format it as XML and use CROSS APPLY -- trick I saw a while back that didn't require built in functions.

    That will convert your comma delimited string to a list of strings. You can then use FOR XML to put them back together.

    Give this a shot:

    SELECT
       E.Id, 
       E.Name, 
       STUFF(
            (
            SELECT ',' +  D.Department AS [text()]
            FROM  (
               SELECT A.[id],  
                 Split.a.value('.', 'VARCHAR(100)') AS DeptId  
               FROM  
                  (SELECT [id],  
                     CAST ('<M>' + REPLACE(Depts, ',', '</M><M>') + '</M>' AS XML) AS String  
                  FROM  Employee
              ) AS A 
            CROSS APPLY String.nodes ('/M') AS Split(a)) A 
            JOIN Departments D ON A.DeptId = D.Id
            WHERE E.Id = A.Id
            FOR XML PATH('')
            ), 1, 1, '') AS Departments
    FROM Employee E
    

    And here is the SQL Fiddle.

    Good luck.

    0 讨论(0)
  • 2021-01-03 03:30

    You can also use a recursive CTE to split the data and then use FOR XML PATH to concatenate the rows into a single row:

    ;with cte (id, name, deptid, depts) as
    (
      select id, name,
        cast(left(depts, charindex(',',depts+',')-1) as varchar(50)) deptid,
             stuff(depts, 1, charindex(',',depts+','), '') depts
      from employee
      union all
      select id, name,
        cast(left(depts, charindex(',',depts+',')-1) as varchar(50)) deptid,
        stuff(depts, 1, charindex(',',depts+','), '') depts
      from cte
      where depts > ''
    ) 
    select e.id, e.name,
      stuff((
             select distinct ', '+ d.dept
             from cte c
             inner join departments d
                on c.deptid = d.id
             where e.id = c.id
             for XML path('')),1,1,'') Depts
    from employee e
    

    See SQL Fiddle with Demo

    Result:

    | ID |     NAME |          DEPTS |
    ----------------------------------
    |  1 |    Kevin |      Accts, HR |
    |  2 | Michelle |             HR |
    |  3 |     Troy |         HR, IT |
    |  4 |   Rheesa |  Accts, HR, IT |
    
    0 讨论(0)
  • 2021-01-03 03:37

    Write a function for splitting comma separated values. I wrote dbo.split

    select * from dbo.split('1,2,3',',') Will return as - Data 1 2 3

    SELECT tact.ActivityID,CONVERT(NVARCHAR(20),tact.createddate,103) AS CallDate,
    ActivityOriginatedByPartyID , (ISNULL(p.firstname,'')+' '+ISNULL(p.lastname,'')) AS PartnerName,
    u.UserName AS PSTName, ccv.codevalue AS CallType
    **, ccv1.codevalue AS CallContext**
    ,tact.ActivityNote AS CallTrackerNote,
    (CONVERT(VARCHAR(20),tact.ActivityTimeSpend) + ' Min') AS CallDuration
    FROM txn_activity tact (NOLOCK)
    INNER JOIN TXN_Party p (NOLOCK) ON p.PartyID = tact.ActivityOriginatedByPartyID 
    INNER JOIN TXN_User u (NOLOCK) ON u.userid = tact.createdby
    INNER JOIN CFG_CodeValue ccv (NOLOCK) ON ccv.codevalueid = tact.ActivityTypeID
    --INNER JOIN CFG_CodeValue ccv1 (NOLOCK) ON ccv1.codevalueid = tact.ActivityContext
    
    **CROSS APPLY  
        dbo.split(tact.ActivityContext,',') split
    inner join 
        dbo.CFG_CodeValue ccv1 (NOLOCK) ON ccv1.codevalueid = split.data**
    
    0 讨论(0)
  • 2021-01-03 03:40
    DECLARE @Departments TABLE 
    (
      ID INT PRIMARY KEY, 
      Dept VARCHAR(32) NOT NULL UNIQUE
    );
    
    DECLARE @Employees TABLE
    (
      ID INT PRIMARY KEY,
      Name NVARCHAR(64) NOT NULL,
      Depts VARCHAR(255) NOT NULL
    );
    
    INSERT @Departments VALUES 
      (1,'HR'),  (2,'Accts'),  (3,'IT');
    
    INSERT @Employees VALUES
      (1,'Kevin','2,1'), (2,'Michelle','1'),
      (3,'Troy','1,3'),  (4,'Rheesa','2,3,1');
    
    SELECT ID, Name, Depts = STUFF((SELECT ',' + d.Dept 
        FROM @Departments AS d
        INNER JOIN @Employees AS ei
        ON ',' + ei.Depts + ',' LIKE '%,' + CONVERT(VARCHAR(12), d.id) + ',%'
        WHERE ei.ID = e.ID
        ORDER BY Dept
        FOR XML PATH, TYPE).value('.[1]', 'nvarchar(max)'), 1, 1, '')
    FROM @Employees AS e
    ORDER BY ID;
    

    The results don't quite match your required results, as the ordering is deterministic (ordered by department name):

    ID      Name        Depts
    ----    --------    ----
    1       Kevin       Accts,HR
    2       Michelle    HR
    3       Troy        HR,IT
    4       Rheesa      Accts,HR,IT
    

    If you want them ordered by the appearance in the comma-separated list, just change:

    ORDER BY Dept
    

    To:

    ORDER BY CHARINDEX( ',' + CONVERT(VARCHAR(12), d.id) + ',', ',' + ei.Depts + ',')
    

    Results:

    ID      Name        Depts
    ----    --------    ----
    1       Kevin       Accts,HR
    2       Michelle    HR
    3       Troy        HR,IT
    4       Rheesa      Accts,IT,HR -- this is the only one affected as it turns out
    

    However, in reality, you should normalize your database. This is an absolute nightmare.

    0 讨论(0)
  • 2021-01-03 03:46

    Also you can use option with dynamic management function sys.dm_fts_parser
    Before script execution you need check full-text component is installed:

    SELECT FULLTEXTSERVICEPROPERTY ('IsFulltextInstalled')
    

    0 = Full-text is not installed. 1 = Full-text is installed. NULL = Invalid input, or error.

    If 0 = Full-text is not installed then this post is necessary to you How to install fulltext on sql server 2008?

    SELECT b.ID, b.Name, STUFF((
    SELECT ',' + d.Dept
    FROM Employees e 
      JOIN Departments d ON d.ID IN(
                                    SELECT display_term 
                                    FROM sys.dm_fts_parser('"' + e.Depts + '"', 1033, NULL, 0) 
                                    WHERE display_term NOT LIKE 'nn%'
                                    )
    WHERE b.ID = e.ID
    ORDER BY d.Dept
    FOR XML PATH('')), 1, 1, '') AS Depts
    FROM Employees b
    

    OR

    SELECT e.ID, e.Name, 
     (
      STUFF((
      SELECT ',' + Dept
      FROM sys.dm_fts_parser('"' + e.Depts + '"', 1033, NULL, 0) p JOIN Departments d ON p.display_term = d.ID
      WHERE display_term NOT LIKE 'nn%'
      FOR XML PATH('')), 1, 1, '')
      ) AS Depts
     FROM Employees e
    
    0 讨论(0)
提交回复
热议问题