Sql 返回在另一个定义了要求和的科目或范围的表中指定的科目总和的查询

Sql 返回在另一个定义了要求和的科目或范围的表中指定的科目总和的查询,sql,tsql,sql-server-2016,Sql,Tsql,Sql Server 2016,我有一个用户正在维护的表格,在那里他们可以使用“统计帐户”定义他们想要汇总的帐户-无论是指定帐户还是范围帐户。您如何构建一个视图,以最好地汇总pr stat帐户和月份的金额。我需要以某种方式使pr.account能够更改where子句 下面我有两个表:DimStatAccount和FactAmount,下面是预期的视图 正如前面所说,动态sql是您所需要的 CREATE TABLE #dimStatAccount (StatAccount varchar(255), Accounts varch

我有一个用户正在维护的表格,在那里他们可以使用“统计帐户”定义他们想要汇总的帐户-无论是指定帐户还是范围帐户。您如何构建一个视图,以最好地汇总pr stat帐户和月份的金额。我需要以某种方式使pr.account能够更改where子句

下面我有两个表:DimStatAccount和FactAmount,下面是预期的视图


正如前面所说,动态sql是您所需要的

CREATE TABLE #dimStatAccount (StatAccount varchar(255), Accounts varchar(255), AccountsRange varchar(255))
INSERT INTO #dimStatAccount VALUES
  ('Stat1', 'in (1000,1020)', null),
  ('Stat2', 'in (1020,2020)', null),
  ('Stat3', null, 'between 1000 and 1999'),
  ('Stat4', null, 'between 2000 and 2999')

CREATE TABLE #factAmount (Account int, [Month] varchar(255), Amount int)
INSERT INTO #factAmount VALUES
  (1000,'jan',500),
  (1000,'feb',460),
  (1010,'jan',799),
  (1010,'jan',855),
  (1010,'feb',633),
  (1020,'feb',522),
  (2000,'jan',436),
  (2000,'jan',946),
  (2000,'jan',374),
  (2010,'jan',683),
  (2010,'feb',492),
  (2020,'jan',437),
  (2020,'feb',834),
  (2030,'jan',944)

CREATE TABLE #result (StatAccount varchar(255), [Month] varchar(255), SumAmount int)

DECLARE @statAccount varchar(255), @accounts varchar(255), @rangeAccounts varchar(255)

DECLARE rcursor CURSOR FOR
  SELECT StatAccount, Accounts, AccountsRange
  FROM #dimStatAccount
OPEN rcursor
FETCH NEXT FROM rcursor
INTO @statAccount, @accounts, @rangeAccounts

WHILE @@FETCH_STATUS = 0
BEGIN
  DECLARE @sql NVARCHAR(max)
  IF @accounts IS NOT NULL
  BEGIN
    SET @Sql = 'INSERT INTO #result '
    SET @sql = @Sql + 'SELECT ''' + @statAccount + ''' AS StatAccount, [MONTH], SUM(f.Amount) AS SumAmount '
    SET @Sql = @Sql + 'FROM #factAmount AS f '
    SET @Sql = @Sql +  'WHERE Account ' + @accounts + ' ' 
    SET @Sql = @Sql +  'GROUP BY [Month]'

    EXEC sp_executesql @Sql

    FETCH NEXT FROM rcursor
    INTO @statAccount, @accounts, @rangeAccounts
  END   
  IF @rangeAccounts IS NOT NULL
  BEGIN
    SET @Sql = 'INSERT INTO #result '
    SET @sql = @Sql + 'SELECT ''' + @statAccount + ''' AS StatAccount, [MONTH], SUM(f.Amount) AS SumAmount '
    SET @Sql = @Sql + 'FROM #factAmount AS f '
    SET @Sql = @Sql +  'WHERE Account ' + @rangeAccounts + ' ' 
    SET @Sql = @Sql +  'GROUP BY [Month]'
    print @Sql
    EXEC sp_executesql @Sql

    FETCH NEXT FROM rcursor
    INTO @statAccount, @accounts, @rangeAccounts
  END
END

CLOSE rcursor 
DEALLOCATE rcursor 

SELECT * FROM #result
结果

StatAccount  Month  SumAmount
-----------------------------
Stat1        feb    982
Stat1        jan    500
Stat2        feb    1356
Stat2        jan    437
Stat3        feb    1615
Stat3        jan    2154
Stat4        feb    1326
Stat4        jan    3820

如前所述,动态sql是您所需要的

CREATE TABLE #dimStatAccount (StatAccount varchar(255), Accounts varchar(255), AccountsRange varchar(255))
INSERT INTO #dimStatAccount VALUES
  ('Stat1', 'in (1000,1020)', null),
  ('Stat2', 'in (1020,2020)', null),
  ('Stat3', null, 'between 1000 and 1999'),
  ('Stat4', null, 'between 2000 and 2999')

CREATE TABLE #factAmount (Account int, [Month] varchar(255), Amount int)
INSERT INTO #factAmount VALUES
  (1000,'jan',500),
  (1000,'feb',460),
  (1010,'jan',799),
  (1010,'jan',855),
  (1010,'feb',633),
  (1020,'feb',522),
  (2000,'jan',436),
  (2000,'jan',946),
  (2000,'jan',374),
  (2010,'jan',683),
  (2010,'feb',492),
  (2020,'jan',437),
  (2020,'feb',834),
  (2030,'jan',944)

CREATE TABLE #result (StatAccount varchar(255), [Month] varchar(255), SumAmount int)

DECLARE @statAccount varchar(255), @accounts varchar(255), @rangeAccounts varchar(255)

DECLARE rcursor CURSOR FOR
  SELECT StatAccount, Accounts, AccountsRange
  FROM #dimStatAccount
OPEN rcursor
FETCH NEXT FROM rcursor
INTO @statAccount, @accounts, @rangeAccounts

WHILE @@FETCH_STATUS = 0
BEGIN
  DECLARE @sql NVARCHAR(max)
  IF @accounts IS NOT NULL
  BEGIN
    SET @Sql = 'INSERT INTO #result '
    SET @sql = @Sql + 'SELECT ''' + @statAccount + ''' AS StatAccount, [MONTH], SUM(f.Amount) AS SumAmount '
    SET @Sql = @Sql + 'FROM #factAmount AS f '
    SET @Sql = @Sql +  'WHERE Account ' + @accounts + ' ' 
    SET @Sql = @Sql +  'GROUP BY [Month]'

    EXEC sp_executesql @Sql

    FETCH NEXT FROM rcursor
    INTO @statAccount, @accounts, @rangeAccounts
  END   
  IF @rangeAccounts IS NOT NULL
  BEGIN
    SET @Sql = 'INSERT INTO #result '
    SET @sql = @Sql + 'SELECT ''' + @statAccount + ''' AS StatAccount, [MONTH], SUM(f.Amount) AS SumAmount '
    SET @Sql = @Sql + 'FROM #factAmount AS f '
    SET @Sql = @Sql +  'WHERE Account ' + @rangeAccounts + ' ' 
    SET @Sql = @Sql +  'GROUP BY [Month]'
    print @Sql
    EXEC sp_executesql @Sql

    FETCH NEXT FROM rcursor
    INTO @statAccount, @accounts, @rangeAccounts
  END
END

CLOSE rcursor 
DEALLOCATE rcursor 

SELECT * FROM #result
结果

StatAccount  Month  SumAmount
-----------------------------
Stat1        feb    982
Stat1        jan    500
Stat2        feb    1356
Stat2        jan    437
Stat3        feb    1615
Stat3        jan    2154
Stat4        feb    1326
Stat4        jan    3820

我从凯文的回答中偷了一桌子东西。可以使用select into变量功能从DimStatAccount表创建动态SQL select语句

CREATE TABLE DimStatAccount (StatAccount varchar(255), Accounts varchar(255), AccountsRange varchar(255))
INSERT INTO DimStatAccount VALUES
  ('Stat1', 'in (1000,1020)', null),
  ('Stat2', 'in (1020,2020)', null),
  ('Stat3', null, 'between 1000 and 1999'),
  ('Stat4', null, 'between 2000 and 2999')

CREATE TABLE FactAmount (Account int, [Month] varchar(255), Amount int)
INSERT INTO FactAmount VALUES
  (1000,'jan',500),
  (1000,'feb',460),
  (1010,'jan',799),
  (1010,'jan',855),
  (1010,'feb',633),
  (1020,'feb',522),
  (2000,'jan',436),
  (2000,'jan',946),
  (2000,'jan',374),
  (2010,'jan',683),
  (2010,'feb',492),
  (2020,'jan',437),
  (2020,'feb',834),
  (2030,'jan',944)

DECLARE @sqlStatement NVARCHAR(MAX) = '';

SELECT @sqlStatement += CONCAT('SELECT ''',StatAccount,''',[Month],SUM(Amount) FROM FactAmount WHERE Account ',ISNULL(Accounts,AccountsRange),' GROUP BY [Month] UNION ALL ')
FROM DimStatAccount
;

SET @sqlStatement = LEFT(@sqlStatement,LEN(@sqlStatement)-10); --remove the final Union All

EXEC sp_executesql @sqlStatement;

我从凯文的回答中偷了一桌子东西。可以使用select into变量功能从DimStatAccount表创建动态SQL select语句

CREATE TABLE DimStatAccount (StatAccount varchar(255), Accounts varchar(255), AccountsRange varchar(255))
INSERT INTO DimStatAccount VALUES
  ('Stat1', 'in (1000,1020)', null),
  ('Stat2', 'in (1020,2020)', null),
  ('Stat3', null, 'between 1000 and 1999'),
  ('Stat4', null, 'between 2000 and 2999')

CREATE TABLE FactAmount (Account int, [Month] varchar(255), Amount int)
INSERT INTO FactAmount VALUES
  (1000,'jan',500),
  (1000,'feb',460),
  (1010,'jan',799),
  (1010,'jan',855),
  (1010,'feb',633),
  (1020,'feb',522),
  (2000,'jan',436),
  (2000,'jan',946),
  (2000,'jan',374),
  (2010,'jan',683),
  (2010,'feb',492),
  (2020,'jan',437),
  (2020,'feb',834),
  (2030,'jan',944)

DECLARE @sqlStatement NVARCHAR(MAX) = '';

SELECT @sqlStatement += CONCAT('SELECT ''',StatAccount,''',[Month],SUM(Amount) FROM FactAmount WHERE Account ',ISNULL(Accounts,AccountsRange),' GROUP BY [Month] UNION ALL ')
FROM DimStatAccount
;

SET @sqlStatement = LEFT(@sqlStatement,LEN(@sqlStatement)-10); --remove the final Union All

EXEC sp_executesql @sqlStatement;


你试过什么?有研究吗?这些表有模式吗?提示:使用适当的软件(MySQL、Oracle、DB2等)和版本(例如,
sql-server-2014
)标记数据库问题很有帮助。语法和功能的差异通常会影响答案。似乎您希望使用动态SQL。我同意@xQbert的观点,使用动态SQL的存储过程将非常简单。只需确保对帐户和帐户范围的输入进行了良好的清理。这是@xQbert的一个好观点,如果没有正确填充,我的答案肯定会分崩离析。我还使用了CONCAT(),它假设SQL Server 2012或更高版本,但是如果使用早期版本,您可以调整为ISNULL()和+连接。您尝试了什么?有研究吗?这些表有模式吗?提示:使用适当的软件(MySQL、Oracle、DB2等)和版本(例如,
sql-server-2014
)标记数据库问题很有帮助。语法和功能的差异通常会影响答案。似乎您希望使用动态SQL。我同意@xQbert的观点,使用动态SQL的存储过程将非常简单。只需确保对帐户和帐户范围的输入进行了良好的清理。这是@xQbert的一个好观点,如果没有正确填充,我的答案肯定会分崩离析。我还使用了CONCAT(),它假定SQL Server 2012或更高版本,但是如果使用早期版本,您可以调整为ISNULL()和+连接。感谢您将插入内容写入原始表,我讨厌这样做。但是,不需要游标或临时表;一个简单的动态SQL选择将解决这个问题感谢您将插入写入原始表,我讨厌这样做。但是,不需要游标或临时表;一个简单的动态SQL选择将解决这个问题,比我的问题要简单得多。美好的我会记住这一点。谢谢,唯一的问题是能够有一个可以返回此结果的视图。我想不可能创建一个执行存储过程的视图?您可以创建一个视图,但您的问题是每次更新维度表时,它都必须更改。因此,在最坏的情况下,只要表发生更改,您就可以触发该表重新创建视图。这比我的要简单得多。美好的我会记住这一点。谢谢,唯一的问题是能够有一个可以返回此结果的视图。我想不可能创建一个执行存储过程的视图?您可以创建一个视图,但您的问题是每次更新维度表时,它都必须更改。因此,在最坏的情况下,只要表发生更改,就可以触发该表重新创建视图。