假设我有e个表-表1、表2和表3。表2在表1和表3上具有外键。表2有"名称"字段。我想从Table3中选择Table1.id和所有匹配的名称(串联)。这是对的查询
CREATE FUNCTION dbo.concat_string(@Input int)
RETURNS VARCHAR(8000)
BEGIN
DECLARE @strList VARCHAR(8000)
SELECT @strList = COALESCE(@strList + ' ', '') + CAST(Table3.Name AS VARCHAR)
FROM Table1
JOIN Table2 ON Table2.Table1_ID = Table1.ID
JOIN Table3 ON Table3.ID = Table2.Table3_ID
WHERE
Table1.ID = @Input
RETURN @strList;
END
SELECT Table1.ID, Table4.cc
FROM Table1 JOIN
(SELECT Table1.ID dbo.concat_string(Table1.ID) as "cc" FROM Table1) Table4
ON Table1.ID = Table4.cID
它按照我想要的方式工作,但太慢了。如何对此进行优化?任何优化都将是有益的。
这是因为您正在为Table1的每一行调用函数,因此会影响您的性能。
第二点是,您使用联接多次调用table1,这会增加一些时间。
我不知道@strList = COALESCE(@strList + ' ', '') + CAST(Table3.Name AS VARCHAR)
是否比FOR XML PATH
和STUFF
更有效地将多行Name连接到一行中,但你可以尝试一下
此外,我建议您在不使用函数的情况下,在一个唯一的查询中完成所有工作(这不是最好的性能)。
试试这个:
SELECT
t.ID
,STUFF((
SELECT ' ,' + CAST(Table3.Name AS VARCHAR)
FROM
Table1 as t1
JOIN Table2
ON Table2.Table1_ID = Table1.ID
JOIN Table3
ON Table3.ID = Table2.Table3_ID
WHERE t1.ID = t.ID
FOR XML PATH('')
), 1, 1, '') as "cc"
FROM
Table1 as t
给我留言。
您遇到了一个常见问题。存储可用于插入、更新、删除或选择的数据(OLTP与OLAP)。
如果您经常需要拆分数据并从中进行选择,我建议您在需要选择之前先存储已拆分的数据。您可以在插入数据时使用上述功能将数据拆分到一个单独的表中,也可以根据您需要的最新数据通过隔夜过程进行拆分。然后,如果需要额外的性能,您可以对拆分的数据进行索引。
简而言之:
- 创建新表
- 在插入数据时,调用split函数,并将拆分后的数据插入到与主数据相关的新表中
- 更改任何select语句以引用新表
这种方法的缺点是增加了对第二个表的维护。