Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/27.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 如何更换';字符串';使用基于group by子句的数值_Sql_Sql Server_Sql Server 2012 - Fatal编程技术网

Sql 如何更换';字符串';使用基于group by子句的数值

Sql 如何更换';字符串';使用基于group by子句的数值,sql,sql-server,sql-server-2012,Sql,Sql Server,Sql Server 2012,我有下表(#temp1),其中我需要根据组“Yearmonth”将列“Formula”中的字符串替换为匹配的输入“VALUE”列 “公式”列可以是任何数学表达式,以便更好地理解我在下面提到的一个简单示例 IDNUM formula INPUTNAME VALUE YEARMONTH --------------------------------------------------------------------- 1

我有下表(#temp1),其中我需要根据组“Yearmonth”将列“Formula”中的字符串替换为匹配的输入“VALUE”列

“公式”列可以是任何数学表达式,以便更好地理解我在下面提到的一个简单示例

  IDNUM  formula                      INPUTNAME      VALUE    YEARMONTH
---------------------------------------------------------------------
  1      imports(398)+imports(399)    imports(398)    17.000  2003:1
  2      imports(398)+imports(399)    imports(398)    56.000  2003:2
  3      imports(398)+imports(399)    imports(399)    15.000  2003:1
  4      imports(398)+imports(399)    imports(399)    126.000 2003:2
例如:从上表中,我需要输出为

Idnum  Formula        Yearmonth
 1.    17.00 +15.00    2003:1
 2.    56.00 +126.00   2003:2
我尝试了以下不同的查询,来自不同的建议,但未能实现。有人能帮我解决这个问题吗

类型1:

SELECT
REPLACE(FORMULA, INPUTName, AttributeValue) AS realvalues, 
yearmonth 
FROM #temp1
GROUP BY yearmonth
类型2: 正在使用XML路径。。。在本例中,它可以工作,但我只需要用值替换字符串,而不需要基于mathematcal操作填充字符串(因为公式可能是任何类型的)

类型3:使用递归…这只返回空值

;with t as (
  select t.*,
         row_number() over (partition by yearmonth order by idnum) as seqnum,
         count(*) over (partition by yearmonth) as cnt
  from #temp1 t


 )

 ,cte as (
  select t.seqnum, t.yearmonth, t.cnt,
         replace(formula, inputname, AttributeValue) as formula1
  from t
  where seqnum = 1
  union all
  select cte.seqnum, cte.yearmonth, cte.cnt,
         replace(CTE.formula1, T.inputname, T.AttributeValue) as formula2
  from cte join
       t
       on cte.yearmonth = t.yearmonth 

       AND  cte.seqnum = t.seqnum + 1 
)
   select row_number() over (order by (select null)) as id,formula1
   from cte
   where seqnum = cnt

这是使用递归CTE的完整工作示例:

DECLARE @DataSource TABLE
(
    [IDNUM] TINYINT
   ,[formula] VARCHAR(MAX)
   ,[INPUTNAME] VARCHAR(128)
   ,[VALUE] DECIMAL(9,3)
   ,[YEARMONTH] VARCHAR(8)
);

INSERT INTO @DataSource ([IDNUM], [formula], [INPUTNAME], [VALUE], [YEARMONTH])
VALUES ('1', 'imports(398)+imports(399)', 'imports(398)', '17.000', '2003:1')
      ,('2', 'imports(398)+imports(399)', 'imports(398)', '56.000', '2003:2')
      ,('3', 'imports(398)+imports(399)', 'imports(399)', '15.000', '2003:1')
      ,('4', 'imports(398)+imports(399)', 'imports(399)', '126.000', '2003:2')
      ,('5', '(imports(391)+imports(392)-imports(393))/imports(394)', 'imports(391)', '5.000', '2003:3')
      ,('6', '(imports(391)+imports(392)-imports(393))/imports(394)', 'imports(392)', '10.000', '2003:3')
      ,('7', '(imports(391)+imports(392)-imports(393))/imports(394)', 'imports(393)', '3.000', '2003:3')
      ,('8', '(imports(391)+imports(392)-imports(393))/imports(394)', 'imports(394)', '-5.000', '2003:3');

WITH DataSource AS
( 
    SELECT ROW_NUMBER() OVER(PARTITION BY [YEARMONTH] ORDER BY [IDNUM]) AS [ReplacementOrderID]
          ,[YEARMONTH]
          ,[formula]
          ,[INPUTNAME] AS [ReplacementString]
          ,[VALUE] AS [ReplacementValue]
    FROM @DataSource
),
RecursiveDataSource AS
(
    SELECT [ReplacementOrderID]
          ,[YEARMONTH]
          ,REPLACE([formula], [ReplacementString], [ReplacementValue]) AS [formula]
    FROM DataSource
    WHERE [ReplacementOrderID] = 1
    UNION ALL
    SELECT DS.[ReplacementOrderID]
          ,DS.[YEARMONTH]
          ,REPLACE(RDS.[formula], DS.[ReplacementString], DS.[ReplacementValue]) AS [formula]
    FROM RecursiveDataSource RDS
    INNER JOIN DataSource DS
        ON RDS.[ReplacementOrderID] + 1 = DS.[ReplacementOrderID]
        AND RDS.[YEARMONTH] = DS.[YEARMONTH]
)
SELECT RDS.[YEARMONTH]
      ,RDS.[formula]
FROM RecursiveDataSource RDS
INNER JOIN 
(
    SELECT [YEARMONTH]
          ,MAX([ReplacementOrderID]) AS [ReplacementOrderID]
    FROM DataSource
    GROUP BY [YEARMONTH]
) DS
    ON RDS.[YEARMONTH] = DS.[YEARMONTH]
    AND RDS.[ReplacementOrderID] = DS.[ReplacementOrderID]
ORDER BY RDS.[YEARMONTH]


通常,您只需要在一条语句中对一个字符串执行多次替换。您可以有许多替换值,只需使用
MAXRECURSION
选项。

这些数字是什么
(398)
(399)
的意思?meIts有点不清楚,只是字符串和“input name”列具有相同的字符串名称。。。数字表示导入类型的不同“ID”…表达式是否始终遵循
imports(X)[+imports(Y)…]格式?如果是这样,为什么不将X和Y存储在另一个表中?或者您是否需要支持除导入以外的其他源,或者仅支持
+
以外的其他操作数?
--Create sample data
DROP TABLE #temp1
CREATE TABLE #temp1 (IDNUM int, formula varchar(max), INPUTNAME varchar(max), VALUE decimal, YEARMONTH varchar(max))
INSERT INTO #temp1 VALUES 
    (1, 'imports(398)+imports(399)', 'imports(398)', 17.000, '2003:1'),
    (2, 'imports(398)+imports(399)', 'imports(398)', 56.000, '2003:2'),
    (3, 'imports(398)+imports(399)', 'imports(399)', 15.000, '2003:1'),
    (4, 'imports(398)+imports(399)', 'imports(399)', 126.000, '2003:2')

--Query
;WITH t as (
    SELECT formula, YEARMONTH, IDNUM
    FROM #temp1
UNION ALL
    SELECT REPLACE(a.formula, b.INPUTNAME, CAST(b.VALUE AS varchar(100))) AS formula, a.YEARMONTH, a.IDNUM
    FROM t a
    JOIN #temp1 b ON a.YEARMONTH = b.YEARMONTH AND a.formula LIKE '%' + b.INPUTNAME + '%'
)
SELECT MIN(IDNUM) AS IDNUM, formula, YEARMONTH
FROM t
WHERE formula not LIKE '%imports(%'
GROUP BY formula, YEARMONTH
DECLARE @DataSource TABLE
(
    [IDNUM] TINYINT
   ,[formula] VARCHAR(MAX)
   ,[INPUTNAME] VARCHAR(128)
   ,[VALUE] DECIMAL(9,3)
   ,[YEARMONTH] VARCHAR(8)
);

INSERT INTO @DataSource ([IDNUM], [formula], [INPUTNAME], [VALUE], [YEARMONTH])
VALUES ('1', 'imports(398)+imports(399)', 'imports(398)', '17.000', '2003:1')
      ,('2', 'imports(398)+imports(399)', 'imports(398)', '56.000', '2003:2')
      ,('3', 'imports(398)+imports(399)', 'imports(399)', '15.000', '2003:1')
      ,('4', 'imports(398)+imports(399)', 'imports(399)', '126.000', '2003:2')
      ,('5', '(imports(391)+imports(392)-imports(393))/imports(394)', 'imports(391)', '5.000', '2003:3')
      ,('6', '(imports(391)+imports(392)-imports(393))/imports(394)', 'imports(392)', '10.000', '2003:3')
      ,('7', '(imports(391)+imports(392)-imports(393))/imports(394)', 'imports(393)', '3.000', '2003:3')
      ,('8', '(imports(391)+imports(392)-imports(393))/imports(394)', 'imports(394)', '-5.000', '2003:3');

WITH DataSource AS
( 
    SELECT ROW_NUMBER() OVER(PARTITION BY [YEARMONTH] ORDER BY [IDNUM]) AS [ReplacementOrderID]
          ,[YEARMONTH]
          ,[formula]
          ,[INPUTNAME] AS [ReplacementString]
          ,[VALUE] AS [ReplacementValue]
    FROM @DataSource
),
RecursiveDataSource AS
(
    SELECT [ReplacementOrderID]
          ,[YEARMONTH]
          ,REPLACE([formula], [ReplacementString], [ReplacementValue]) AS [formula]
    FROM DataSource
    WHERE [ReplacementOrderID] = 1
    UNION ALL
    SELECT DS.[ReplacementOrderID]
          ,DS.[YEARMONTH]
          ,REPLACE(RDS.[formula], DS.[ReplacementString], DS.[ReplacementValue]) AS [formula]
    FROM RecursiveDataSource RDS
    INNER JOIN DataSource DS
        ON RDS.[ReplacementOrderID] + 1 = DS.[ReplacementOrderID]
        AND RDS.[YEARMONTH] = DS.[YEARMONTH]
)
SELECT RDS.[YEARMONTH]
      ,RDS.[formula]
FROM RecursiveDataSource RDS
INNER JOIN 
(
    SELECT [YEARMONTH]
          ,MAX([ReplacementOrderID]) AS [ReplacementOrderID]
    FROM DataSource
    GROUP BY [YEARMONTH]
) DS
    ON RDS.[YEARMONTH] = DS.[YEARMONTH]
    AND RDS.[ReplacementOrderID] = DS.[ReplacementOrderID]
ORDER BY RDS.[YEARMONTH]