Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 有没有比数据透视表或使用XML和节点更有效的滑动列的方法_Sql_Sql Server - Fatal编程技术网

Sql 有没有比数据透视表或使用XML和节点更有效的滑动列的方法

Sql 有没有比数据透视表或使用XML和节点更有效的滑动列的方法,sql,sql-server,Sql,Sql Server,我想知道是否还有其他方法可以分割列,或者比这两种方法更好的方法 我要写一些代码,这样我们可以说同一种语言 --CREATING TABLE CREATE TABLE BOOKS( ID VARCHAR(MAX) NULL ) /* BOOKS PRODUCTID, NAME, PAGES, WEIGHT, SIZE, TYPE */ INSERT INTO BOOKS (ID) VALUES('B001,INTRODUCTION TO SQL,500,100G,MID,TECH')

我想知道是否还有其他方法可以分割列,或者比这两种方法更好的方法

我要写一些代码,这样我们可以说同一种语言

--CREATING TABLE
CREATE TABLE BOOKS(
ID VARCHAR(MAX) NULL
) 
/*
  BOOKS 
  PRODUCTID, NAME, PAGES, WEIGHT, SIZE, TYPE
*/
INSERT INTO BOOKS (ID)
VALUES('B001,INTRODUCTION TO SQL,500,100G,MID,TECH')
      ,('B002,ADVANCED SQL SERVER PRACTICES,200,200G,BIG,TECH')
      ,('B003,SQL SERVER PERFORMANCE,1000,500G,BIG,TECH')
      ,('B004,SQL SERVER MANUAL,50,30G,SMALL,TECH')
          ,('B004,SQL SERVER MANUAL,50,30G,SMALL,TECH')
这将是我的演示表,正如您所看到的,我有一个带有逗号分隔值的表

为了分割这些值,我将使用pivot和CTE组合

/*PIVOTING TABLE, ASIGNING A RN TO COLUMNS AND GETTING BACK VALUES*/
WITH C AS(
SELECT ID
      ,value 
      ,ROW_NUMBER() OVER(PARTITION BY ID ORDER BY (SELECT NULL)) as rn
FROM BOOKS BO
    CROSS APPLY STRING_SPLIT(ID, ',') AS BK
)
SELECT ID
      ,[1] AS PRODUCTID
      ,[2] AS NAME
      ,[3] AS PAGES
      ,[4] AS WEIGHT
      ,[5] AS SIZE
      ,[6] AS TYPE
FROM C
PIVOT(
    MAX(VALUE)
    FOR RN IN([1],[2],[3],[4],[5],[6])  
) as PVT
它工作正常,但在本例中,它返回的字符串顺序不保证为Ex,1,2,3,4。column1=1,column2=3 column3=2 column4=4,我希望得到1,2,3,4 另一个是众所周知的stackoverflow,它使用XML和节点

SELECT DISTINCT
    S.a.value('(/H/r)[1]', 'VARCHAR(100)') AS PRODUCTID
   ,S.a.value('(/H/r)[2]', 'VARCHAR(100)')  AS NAME
   , S.a.value('(/H/r)[3]', 'VARCHAR(100)') AS PAGES
   , S.a.value('(/H/r)[4]', 'VARCHAR(100)') AS WEIGHT
   , S.a.value('(/H/r)[5]', 'VARCHAR(100)') AS SIZE
   , S.a.value('(/H/r)[6]', 'VARCHAR(100)') AS TYPE
FROM
(
SELECT *,CAST (N'<H><r>' + REPLACE(ID, ',', '</r><r>')  
               + '</r></H>' AS XML) AS [vals]
FROM BOOKS) d 
CROSS APPLY d.[vals].nodes('/H/r') S(a) 
另一个是众所周知的stackoverflow,它使用XML和节点

SELECT DISTINCT
    S.a.value('(/H/r)[1]', 'VARCHAR(100)') AS PRODUCTID
   ,S.a.value('(/H/r)[2]', 'VARCHAR(100)')  AS NAME
   , S.a.value('(/H/r)[3]', 'VARCHAR(100)') AS PAGES
   , S.a.value('(/H/r)[4]', 'VARCHAR(100)') AS WEIGHT
   , S.a.value('(/H/r)[5]', 'VARCHAR(100)') AS SIZE
   , S.a.value('(/H/r)[6]', 'VARCHAR(100)') AS TYPE
FROM
(
SELECT *,CAST (N'<H><r>' + REPLACE(ID, ',', '</r><r>')  
               + '</r></H>' AS XML) AS [vals]
FROM BOOKS) d 
CROSS APPLY d.[vals].nodes('/H/r') S(a) 
它也能像预期的那样工作,但别误会我的意思,如果你不在初级水平以上,它很难解释,也有点让人困惑


还有什么更好的方法可以在sql server中拆分列,microsoft是否为此实现了一个新功能,或者您知道其他方法吗

就我个人而言,我的方法是将该值视为一个带分隔符的项,然后使用交叉表将其透视。由于顺序位置很重要,而且字符串_SPLIT不能保证这一点,因此在这里是一个更好的选择:

SELECT MAX(CASE DS.ItemNumber WHEN 1 THEN NULLIF(DS.Item,'') END) AS PRODUCTID,
       MAX(CASE DS.ItemNumber WHEN 2 THEN NULLIF(DS.Item,'') END) AS [NAME],
       MAX(CASE DS.ItemNumber WHEN 3 THEN NULLIF(DS.Item,'') END) AS PAGES,
       MAX(CASE DS.ItemNumber WHEN 4 THEN NULLIF(DS.Item,'') END) AS WEIGHT,
       MAX(CASE DS.ItemNumber WHEN 5 THEN NULLIF(DS.Item,'') END) AS SIZE,
       MAX(CASE DS.ItemNumber WHEN 6 THEN NULLIF(DS.Item,'') END) AS [TYPE]
FROM dbo.BOOKS B
     CROSS APPLY dbo.DelimitedSplit8K_LEAD(B.ID,',') DS
GROUP BY B.ID;

就我个人而言,我的方法是将该值视为一个分隔的项,然后使用交叉表对其进行透视。由于顺序位置很重要,而且字符串_SPLIT不能保证这一点,因此在这里是一个更好的选择:

SELECT MAX(CASE DS.ItemNumber WHEN 1 THEN NULLIF(DS.Item,'') END) AS PRODUCTID,
       MAX(CASE DS.ItemNumber WHEN 2 THEN NULLIF(DS.Item,'') END) AS [NAME],
       MAX(CASE DS.ItemNumber WHEN 3 THEN NULLIF(DS.Item,'') END) AS PAGES,
       MAX(CASE DS.ItemNumber WHEN 4 THEN NULLIF(DS.Item,'') END) AS WEIGHT,
       MAX(CASE DS.ItemNumber WHEN 5 THEN NULLIF(DS.Item,'') END) AS SIZE,
       MAX(CASE DS.ItemNumber WHEN 6 THEN NULLIF(DS.Item,'') END) AS [TYPE]
FROM dbo.BOOKS B
     CROSS APPLY dbo.DelimitedSplit8K_LEAD(B.ID,',') DS
GROUP BY B.ID;

如果2016+,另一个选项是JSON

JSON似乎优于XML,特别是在选择片段和选择值方面

范例


如果2016+,另一个选项是JSON

JSON似乎优于XML,特别是在选择片段和选择值方面

范例


为什么要存储分隔数据?数据首先应该是6个独立的列,因此您的表格应该有6列,而不是1列。我在工作中处理客户数据时多次遇到过这种情况,请相信我,在进行数据分析时,数据并不总是专门结构化的。请参阅本文。它描述了一个也返回列顺序的拆分器函数。你应该看看它的改进版本@user1443098:那是我,@user1443098,不是Alvaro;是的,Eirikur在发表之前,对Jeff谈了很多关于这个函数的事情,并表示了他的祝福。在我看来,这两个函数是SSC社区的一个很好的例子。为什么要存储分隔数据?数据首先应该是6个独立的列,因此您的表格应该有6列,而不是1列。我在工作中处理客户数据时多次遇到过这种情况,请相信我,在进行数据分析时,数据并不总是专门结构化的。请参阅本文。它描述了一个也返回列顺序的拆分器函数。你应该看看它的改进版本@user1443098:那是我,@user1443098,不是Alvaro;是的,Eirikur在发表之前,对Jeff谈了很多关于这个函数的事情,并表示了他的祝福。在我看来,这两个功能是SSC社区的一个很好的例子。你有没有重新设置它?@user1443098我想我不必这样做。尽管Larnu的函数令人印象深刻,但它仍然是一个表值函数和聚合,而不是本机函数!我认为Jeff的基准测试表明情况并非总是如此。就个人而言,在我的家庭工作站i7 8700 32GB RAM上,我发现带630行分隔符的DSPLIT8K_需要10毫秒,而JSON解决方案平均需要16毫秒。3130时48分对83分。奇怪的是,在15000行时,它们在PAR上,然后在80000行,JSON慢得多,在100MS~VS2000毫秒之间。在400000行时,JSON慢了几秒钟。本机函数并不总是更好。例如,看看糟糕的格式函数:@Larnu格式化功能是一个廉价的镜头:你把它重新放在板凳上了吗?@user1443098我想我不必这么做。尽管Larnu的函数令人印象深刻,但它仍然是一个表值函数和聚合,而不是本机函数!我认为Jeff的基准测试表明情况并非总是如此。就个人而言,在我的家庭工作站i7 8700 32GB RAM上,我发现带630行分隔符的DSPLIT8K_需要10毫秒,而JSON解决方案平均需要16毫秒。3130时48分对83分。奇怪的是,在15000行时,它们在PAR上,然后在80000行,JSON慢得多,在100MS~VS2000毫秒之间。在400000行时,JSON慢了几秒钟。本机函数并不总是更好。例如,看看糟糕的格式函数:@Larnu格式化功能是一个廉价的功能: