我正在尝试使用一个使用表变量的查询来构建报表,但它只会导致超时。涉及大量数据,但它仍然在SSMS中正确执行。我不确定原因是表变量,还是我只能进行其他性能调整,所以我正在寻求建议。基本上,我正在做的是对某些总账科目进行分组,使其属于一个类别,然后将这些类别用作SSRS中的列组。其余数据显示供应商付款的总和达到这些总帐类别。
declare @VendorRebateGL table
(
Rebate_type varchar(255)
,GL_Account int
)
INSERT INTO @VendorRebateGL (Rebate_type, GL_Account)
VALUES
('Category1', '5020'),
('Category1', '5021'),
('Category1', '5022'),
('Category2', '5040'),
('Category2', '5041'),
('Category3', '5042'),
('Category3', '5043'),
SELECT
[Vendor No_]
,a.[Posting Date]
,CAST(SUM([Purchase (LCY)]) AS BIGINT)
,[G_L Account No_]
,c.Rebate_type
FROM [DATABASE].[dbo].[Vendor Ledger] a
LEFT JOIN [G_L Entry] b
ON a.[Vendor No_] = b.[Source No_]
INNER JOIN @VendorRebateGL c
ON b.[G_L Account No_] = c.GL_Account
WHERE a.[Document Type] in (2,3)
AND a.[Posting Date] BETWEEN '2014-06-01 00:00:00.000' and '2014-06-30 00:00:00.000'
AND [G_L Account No_] IN (
5020
,5021
,5022
,5040
,5041
,5042
,5043
)
AND (a.Description like 'Invoice%' OR a.Description like 'Credit%')
GROUP BY
[Vendor No_]
,a.[Posting Date]
,[G_L Account No_]
,c.Rebate_type
ORDER BY a.[Posting Date]
答案 0 :(得分:1)
尝试用实际临时表替换表变量。问题是优化器没有关于表变量的详细信息,并且总是假设它们包含1行,这可能导致一些非常糟糕的决定。作为额外的好处,您可以在加入列GL_Account
上创建索引,这也应该有助于提高性能。
create table #VendorRebateGL
(
Rebate_type varchar(255)
,GL_Account int
)
create index IX_VRGL_GLA on #VendorRebateGL(GL_Account) include (Rebate_type)
INSERT INTO #VendorRebateGL (Rebate_type, GL_Account)
...
答案 1 :(得分:0)
有不同的方法来实现它。
方法1:使用表值构造函数
SELECT
[Vendor No_]
,a.[Posting Date]
,CAST(SUM([Purchase (LCY)]) AS BIGINT)
,[G_L Account No_]
,c.Rebate_type
FROM [DATABASE].[dbo].[Vendor Ledger] a
LEFT JOIN [G_L Entry] b
ON a.[Vendor No_] = b.[Source No_]
INNER JOIN
(VALUES
('Category1', '5020'),
('Category1', '5021'),
('Category1', '5022'),
('Category2', '5040'),
('Category2', '5041'),
('Category3', '5042'),
('Category3', '5043'),
) AS c(Rebate_type, GL_Account)
ON b.[G_L Account No_] = c.GL_Account
WHERE a.[Document Type] in (2,3)
AND a.[Posting Date] BETWEEN '2014-06-01 00:00:00.000' and '2014-06-30 00:00:00.000'
AND [G_L Account No_] IN (
5020
,5021
,5022
,5040
,5041
,5042
,5043
)
AND (a.Description like 'Invoice%' OR a.Description like 'Credit%')
GROUP BY
[Vendor No_]
,a.[Posting Date]
,[G_L Account No_]
,c.Rebate_type
ORDER BY a.[Posting Date]
方法2:使用公用表表达式(CTE)。您还可以使用表值构造函数来构建CTE。
;WITH VendorRebateGL(Rebate_type, GL_Account)
AS
(SELECT 'Category1', '5020'
UNION ALL
SELECT 'Category1', '5021'
UNION ALL
SELECT 'Category1', '5022'
UNION ALL
SELECT 'Category2', '5040'
UNION ALL
SELECT 'Category2', '5041'
UNION ALL
SELECT 'Category3', '5042'
UNION ALL
SELECT 'Category3', '5043'
)
SELECT
[Vendor No_]
,a.[Posting Date]
,CAST(SUM([Purchase (LCY)]) AS BIGINT)
,[G_L Account No_]
,c.Rebate_type
FROM [DATABASE].[dbo].[Vendor Ledger] a
LEFT JOIN [G_L Entry] b
ON a.[Vendor No_] = b.[Source No_]
INNER JOIN VendorRebateGL c
ON b.[G_L Account No_] = c.GL_Account
WHERE a.[Document Type] in (2,3)
AND a.[Posting Date] BETWEEN '2014-06-01 00:00:00.000' and '2014-06-30 00:00:00.000'
AND [G_L Account No_] IN (
5020
,5021
,5022
,5040
,5041
,5042
,5043
)
AND (a.Description like 'Invoice%' OR a.Description like 'Credit%')
GROUP BY
[Vendor No_]
,a.[Posting Date]
,[G_L Account No_]
,c.Rebate_type
ORDER BY a.[Posting Date]
方法3:如果数据集不够大,请使用 CASE 语句。
SELECT
[Vendor No_]
,a.[Posting Date]
,CAST(SUM([Purchase (LCY)]) AS BIGINT)
,[G_L Account No_]
, CASE WHEN [G_L Account No_] IN (5020, 5021, 5022) THEN 'Category1'
WHEN [G_L Account No_] IN (5040, 5041) THEN 'Category2'
WHEN [G_L Account No_] IN (5042, 5043) THEN 'Category3'
END AS Rebate_type
FROM [DATABASE].[dbo].[Vendor Ledger] a
LEFT JOIN [G_L Entry] b
ON a.[Vendor No_] = b.[Source No_]
WHERE a.[Document Type] in (2,3)
AND a.[Posting Date] BETWEEN '2014-06-01 00:00:00.000' and '2014-06-30 00:00:00.000'
AND [G_L Account No_] IN (
5020
,5021
,5022
,5040
,5041
,5042
,5043
)
AND (a.Description like 'Invoice%' OR a.Description like 'Credit%')
GROUP BY
[Vendor No_]
,a.[Posting Date]
,[G_L Account No_]
,c.Rebate_type
ORDER BY a.[Posting Date]
方法4:为VendorRebateGL创建物理表。在查询中使用它。