Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/68.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 Server CTE查询-行到单个分隔字符串字段_Sql_Sql Server - Fatal编程技术网

SQL Server CTE查询-行到单个分隔字符串字段

SQL Server CTE查询-行到单个分隔字符串字段,sql,sql-server,Sql,Sql Server,我在SQL Server中有以下数据: 数据创建: -- First we create some test data. CREATE TABLE E ( [Epinum] VARCHAR(9), [RTyp] VARCHAR(120), [Date] DATETIME ); GO INSERT INTO E ([Epinum], [RTyp], [Date]) VALUES ('1', '', CONVERT(datetime, '2002-11-26 14

我在SQL Server中有以下数据:

数据创建:

-- First we create some test data.
CREATE TABLE E
(
     [Epinum] VARCHAR(9), 
     [RTyp] VARCHAR(120), 
     [Date] DATETIME
);
GO

INSERT INTO E ([Epinum], [RTyp], [Date])
VALUES ('1', '', CONVERT(datetime, '2002-11-26 14:18:00', 20)),
       ('2', '', CONVERT(datetime, '2002-11-24 15:15:00', 20)),
       ('3', '', CONVERT(datetime, '2002-12-17 11:12:00', 20)),
       ('4', '', CONVERT(datetime, '2002-12-09 19:57:00', 20)),
       ('5', '', CONVERT(datetime, '2002-12-11 06:00:00', 20)),
       ('6', '', CONVERT(datetime, '2002-12-19 12:31:00', 20)),
       ('7', '', CONVERT(datetime, '2002-12-15 08:39:00', 20)),
       ('8', '', CONVERT(datetime, '2002-12-20 08:39:00', 20)),
       ('9', '', CONVERT(datetime, '2002-12-13 08:39:00', 20)),
       ('10', '', CONVERT(datetime, '2002-12-16 08:39:00', 20)),
       ('11', '', CONVERT(datetime, '2002-12-14 08:39:00', 20));
GO

CREATE TABLE UJ
(
    [Epinum] VARCHAR(9), 
    [RTyp] VARCHAR(3)
);
GO

INSERT INTO UJ ([Epinum], [RTyp])
VALUES ('1', '111'), ('1', '222'), ('1', '333'), ('1', '444'),
       ('2', '111'),
       ('3', '111'), ('3', '222'), ('3', '333'),
       ('4', '111'),
       ('5', '111'), ('5', '222'), ('5', '333'), ('5', '444'), 
       ('5', '555'), ('5', '666'), ('5', '777'), ('5', '888'),
       ('7', '111'),
       ('8', '111'),
       ('9', '111'), ('9', '222');
GO
T-SQL查询:

-- Now build a query that will create the data we want. 
;WITH Tmp AS
(
    SELECT 
        *, 
        ROW_NUMBER() OVER (PARTITION BY Epinum ORDER BY Epinum) AS rownum
    FROM 
        UJ 
) 
SELECT DISTINCT 
    Epinum, 
    (SELECT 
         RTyp + CASE 
                   WHEN t.rownum = (SELECT MAX(rownum) FROM Tmp WHERE Epinum = s.Epinum) 
                      THEN '' 
                      ELSE '|' 
                END 
     FROM Tmp AS t
     WHERE t.Epinum = s.Epinum 
     FOR XML PATH(''), TYPE).value('(.)[1]', 'VARCHAR(MAX)') AS Piped 
FROM 
    Tmp AS s;
GO

-- Great. Now we update the E table, joining on Epinum. 
;WITH Tmp AS
(
    SELECT 
        *, ROW_NUMBER() OVER (PARTITION BY Epinum ORDER BY Epinum) AS rownum
    FROM
        UJ 
) 
UPDATE E
SET e.RTyp = q.Piped 
FROM 
    (SELECT DISTINCT 
         Epinum, 
         (SELECT RTyp + CASE 
                           WHEN t.rownum = (SELECT MAX(rownum) FROM Tmp WHERE Epinum = s.Epinum) 
                              THEN '' 
                              ELSE '|' 
                        END 
          FROM Tmp AS t
          WHERE t.Epinum = s.Epinum 
          FOR XML PATH(''), TYPE).value('(.)[1]', 'VARCHAR(MAX)') AS Piped 
      FROM 
          Tmp AS s) AS q 
INNER JOIN 
    E AS e ON q.Epinum = e.Epinum;
GO
这将获取特定Epinum的所有RTyp列,然后管道对它们进行定界并更新表E中的RTyp。这非常有效,但问题是,生产中的表E约有2.3M行,UJ约为900k(两者都有更多的列),并且此查询执行更新所需的时间太长


如何使此查询更高效?

如果您使用的是最新版本的SQL Server,可以尝试


首先,为什么要尝试将分隔数据填充到生产系统中?它违反了1NF。你真的是说你在尝试用超过900k条目的分隔字符串吗?这是一个性能黑洞的配方。不仅仅是将数据推到那里,而是在以后对其进行解析。“你真的是说你正在尝试制作一些带有900k条目的分隔字符串吗?”不,我只是说有900k行。分隔字符串的最大大小为120个字符40 x 3个字符。“为什么您要首先尝试将分隔数据填充到生产系统中?它违反1NF。”我知道这一点,但我们已经准备好使此数据符合标准-此字段需要管道分隔值。从我手上拿开,理解被铐上手铐的事。你能发布执行计划吗?那么实际的表定义和索引呢?没有这些细节,我们只能猜测。它说这是“表值函数[XML阅读器]成本:96%”,所以我想问题是,我们是否可以创建管道字符串,而不必对XML执行
?这不运行,要更新吗?Msg 10753,15级,状态3,第93行函数“ROW_NUMBER”必须有OVER子句。谢谢您的时间。我不能使用SQL Server 2017。抱歉,最多2016年。已更正查询。对不起,你不能用。
SELECT Epinum, STRING_AGG(Rtyp, '|')  delimited
FROM uj
GROUP BY Epinum;
UPDATE E 
SET e.RTyp = q.Piped 
FROM (
    SELECT Epinum, Piped = STUFF(
        (SELECT '|' + RTyp 
         FROM UJ 
         WHERE Epinum = t.Epinum 
         FOR XML PATH ('')), 1, 1, '') 
    FROM UJ AS t 
    GROUP BY Epinum) AS q INNER JOIN E AS e 
        ON q.Epinum = e.Epinum;
GO