1

我正在构建一个查询,最新步骤涉及添加一个SELECT COUNT(*) FROM [modification]子句以允许我检测查询的最后一行,但这会破坏性能:

SELECT CONCAT(
      IIF(row_number() OVER (ORDER BY forecastId) % 50000 = 1,
          CONCAT('INSERT INTO modification (userId, epochTime, ',
                 'forecastId, description, auxText, auxDate) VALUES ('), 
          '    ('),
      userId, ',',
      epochTime, ',',
      forecastId, ',',
      '''', dbo.encode4MySql(description), ''',',
      '''', dbo.encode4MySql(auxText), ''',',
      '''', CONVERT(VARCHAR(20), auxDate, 120), ''')',
      IIF(row_number() OVER (ORDER BY forecastId) % 50000 = 0
          OR row_number() OVER (ORDER BY forecastId) = 
                      (SELECT COUNT(*) FROM modification),
          '; COMMIT;', ','))
FROM modification
ORDER BY forecastId;

如果你看不到我在做什么,我一次构建INSERT () VALUES (),(),(),...50000 行的语句。

请限制对评论的完全替代方法的建议。我正在寻找一种方法来在这里找到最后一个行号,而不会大大降低查询速度 - 它确实如此。

我对查询计划不是很熟悉,但如果有帮助可以在这里发布一个。我在这里的相关问题中尝试了很多东西,但没有什么可以开始工作。

4

3 回答 3

1

您有一个相当复杂的表达式,因此 SQL Server 可能不会对其进行优化。将逻辑移至FROM子句:

FROM (SELECT m.*, COUNT(*) OVER () as num_rows
      FROM modification m
     ) m

然后num_rows在其余的查询中使用。

于 2017-09-09T17:59:26.813 回答
1

另一种选择是order by forecastId desc在决赛中or

IIF(row_number() OVER (ORDER BY forecastId) % 50000 = 0
          OR row_number() OVER (ORDER BY forecastId desc) = 1,
          '; COMMIT;', ','))
于 2017-09-10T13:30:10.990 回答
0

假设您不想更改当前设计,您可以在最后添加一个额外的 UNION ALL 步骤。通过查看您的查询,看起来更改查询的唯一目的是在末尾添加一个 COMMIT。

CURRENT QUERY
UNION ALL
SELECT 'COMMIT;';

让我知道这是否适合你。

***********更新*********

我认为这个查询更容易排除故障。看看它是否会表现得更好。您必须为您的表格插入 CTE 部分。

SELECT BusinessEntityID,JobTitle,HireDate INTO dbo.TestTable FROM [HumanResources].[Employee]
SELECT TOP 0 BusinessEntityID,JobTitle,HireDate INTO dbo.TestTable2 FROM [HumanResources].[Employee]

SET NOCOUNT ON


WITH CTE AS (SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) Col, 
    ' (' + 
    CAST(BusinessEntityID AS VARCHAR(20)) + 
    ', ''' + 
    JobTitle + 
    ''', ''' + 
    CONVERT(VARCHAR(20), HireDate, 120) +
    ''')' Query
FROM TestTable
) 
    SELECT 
        CASE 
        WHEN COL % 50 = 0 THEN ', ' + Query + ' COMMIT;' 
        WHEN COL % 50 = 1 THEN ' INSERT INTO dbo.TestTable2 (BusinessEntityID, JobTitle, HireDate) VALUES ' + Query
        ELSE ', ' + Query 
        END 
    FROM CTE
UNION ALL SELECT 'COMMIT;'
于 2017-09-10T02:32:33.473 回答