2017-09-25 60 views
0

我需要一些幫助。我已經使用STUFFFOR XML創建了幾乎我想要的結果。我只需要更進一步,以便每個PID都有一個路由。SQL Server中的多個複雜字符串連接

所以我有這樣的SQL代碼:

select 
    pid, 
    STUFF((select ' ' + 
       right('00' + cast(direction as nvarchar(MAX)), 2) + ':' + 
       + CAST(node_id AS NVARCHAR(MAX)) 
      from Path_Devices 
      where (path_id = paths.path_id) 
      group by path_id, node_id, node_index 
      order by path_id, node_index 
      FOR XML PATH(''), TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '') AS ROUTE 
from 
    Path_Devices paths 
join 
    Path p on p.id = paths.path_id 
group by 
    path_id, pid, direction 

產生這樣的:

enter image description here

我需要的ROUTE欄多了一個連接來進行,這樣我的結果集爲1每個pid的完整路線,如下所示:

enter image description here

我的首選是讓整個結果由數據庫生成,並且不需要任何後端的Java處理。這也將是使用JdbcTemplate創建和傳遞的更大的select語句的一部分。目標是在不對數據庫進行任何更改或添加存儲過程的情況下完成此任務。只是讓它變得更具挑戰性。 ;-)

所以問題是我如何堆疊行串值的多個連接來獲得我想要的結果?提前感謝您的幫助!

這裏是我的表:

CREATE TABLE [dbo].[Path](
    [id] [int] IDENTITY(1,1) NOT NULL, 
    [direction] [tinyint] NOT NULL, 
    [pid] [uniqueidentifier] NULL 
) ON [PRIMARY] 

set identity_insert Path ON 
insert into Path (id, direction, pid) values 
    (1,0,'7E814659-1BE3-4941-9710-D78731E70E07'), 
    (2,1,'7E814659-1BE3-4941-9710-D78731E70E07') , 
    (3,0,'67C8CB0D-8AFD-46E4-B06C-70EA19A949A3'), 
    (4,1,'67C8CB0D-8AFD-46E4-B06C-70EA19A949A3'), 
    (5,0,'9DADA1DD-F73C-4210-8DDD-A000ED1B9325'), 
    (6,1,'9DADA1DD-F73C-4210-8DDD-A000ED1B9325'), 
    (7,0,'BC2CF5D6-08EB-4530-B354-818039F24A8F'), 
    (8,1,'BC2CF5D6-08EB-4530-B354-818039F24A8F'), 
    (9,0,'BC2CF5D6-08EB-4530-B354-818039F24A8F'), 
    (10,1,'BC2CF5D6-08EB-4530-B354-818039F24A8F') 

CREATE TABLE [dbo].[Path_Devices](
    [path_id] [int] NOT NULL, 
    [node_id] [int] NOT NULL, 
    [node_index] [int] NOT NULL 
) ON [PRIMARY] 

insert into Path_Devices (path_id, node_id, node_index) values 
    (1,21,0), 
    (1,2024,1), 
    (1,2023,2), 
    (1,2022,3), 
    (1,2011,4), 
    (2,2011,0), 
    (2,2042,1), 
    (2,2043,2), 
    (2,2044,3), 
    (2,41,4), 
    (3,21,0), 
    (3,2024,1), 
    (3,2023,2), 
    (3,2022,3), 
    (3,2011,4), 
    (4,2011,0), 
    (4,2042,1), 
    (4,2043,2), 
    (4,2044,3), 
    (4,41,4), 
    (5,60,0), 
    (5,2062,1), 
    (5,2081,2), 
    (6,2081,0), 
    (6,2072,1), 
    (6,2073,2), 
    (6,70,3), 
    (7,41,0), 
    (7,2044,1), 
    (8,2044,0), 
    (8,3802,1), 
    (9,3802,0), 
    (9,2073,1), 
    (9,2072,2), 
    (9,2071,3) 

使用您正在使用的是哪個版本SQL Server 2012年或2014年

回答

0

,以下是2012+基地。

;with Path_Devices(pid,path_id,direction,node_id) AS (
    select 'aaaaaaaaaaaaaaaa',1,0,21 union all 
    select 'aaaaaaaaaaaaaaaa',1,0,2024 union all 
    select 'aaaaaaaaaaaaaaaa',1,0,2023 union all 
    select 'aaaaaaaaaaaaaaaa',1,0,2022 union all 
    select 'aaaaaaaaaaaaaaaa',1,0,2021 union all 
    select 'aaaaaaaaaaaaaaaa',2,1,2011 union all 
    select 'aaaaaaaaaaaaaaaa',2,1,2042 union all 
    select 'aaaaaaaaaaaaaaaa',2,1,2043 union all 
    select 'aaaaaaaaaaaaaaaa',2,1,2044 union all 
    select 'aaaaaaaaaaaaaaaa',2,1,41 
) 
    /* your statement 
    select 
    pid, 
    STUFF((select ' ' + 
       right('00' + cast(direction as nvarchar(MAX)), 2) + ':' + 
       + CAST(node_id AS NVARCHAR(MAX)) 
      from Path_Devices 
      where (path_id = paths.path_id) 
      group by path_id,direction, node_id 
      order by path_id 
      FOR XML PATH(''), TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '') AS ROUTE 
from Path_Devices paths 
group by path_id, pid, direction 
*/ 
    select 
    pid, 
    STUFF((select case when LAG(direction)over(partition by pid order by path_id,direction)=direction then ' ' else ',' end + 
       right('00' + cast(direction as nvarchar(MAX)), 2) + ':' + 
       + CAST(node_id AS NVARCHAR(MAX)) 
      from Path_Devices 
      where (pid = paths.pid) 
      group by pid,path_id,direction, node_id 
      order by path_id,direction 
      FOR XML PATH(''), TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '') AS ROUTE 
from Path_Devices paths 
group by pid 
 
+------------------+----------------------------------------------------------------------------+ 
| pid    | ROUTE                  | 
+------------------+----------------------------------------------------------------------------+ 
| aaaaaaaaaaaaaaaa | 0:21 00:2024 00:2023 00:2022 00:2021,01:2011 01:2042 01:2043 01:2044 01:41 | 
+------------------+----------------------------------------------------------------------------+ 
+0

我們正在爲SQL Server 2014開發,你能否提供了'With'部分更多的解釋,請。 –

+1

@ Nelda.techspiress僅用於創建測試數據,它僅支持到2012年的LAG函數,我使用LAG是爲了獲取上一行的方向,如果當前值與前一行不同,則使用逗號(, )替換空白。 [LAG](https://docs.microsoft.com/en-us/sql/t-sql/functions/lag-transact-sql) –

+0

謝謝。我收到了關於方向和pid的綁定錯誤。 –

0

你可以嘗試這樣的事情:

with cte as (
select 
    pid, 
    STUFF((select ' ' + 
       right('00' + cast(direction as nvarchar(MAX)), 2) + ':' + 
       + CAST(node_id AS NVARCHAR(MAX)) 
      from Path_Devices 
      where (path_id = paths.path_id) 
      group by path_id, node_id, node_index 
      order by path_id, node_index 
      FOR XML PATH(''), TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '') AS ROUTE 
from 
    Path_Devices paths 
join 
    Path p on p.id = paths.path_id 
group by 
    path_id, pid, direction 
) 
select Distinct 
    pid, 
    STUFF((select ' ' + 
       b.route 
      from cte b 
      where (a.pid = b.pid) 
      group by b.pid, b.route 
      order by b.pid, b.route 
      FOR XML PATH(''), TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '') AS ROUTE 
from 
    cte A 
+0

我喜歡這個,但它似乎有一個無限循環。我跑了7分鐘沒有結果。如果您有其他建議,請張貼更多。謝謝! –

+1

這種技術有一些性能問題取決於來源。請向其他人提供表格結構和樣本數據,我會幫助你更好。和你的SQL Server版本 –