我需要你的帮助来动态创建查询, 如何从其他表中的公式填充数据值。
以下示例
Table A
ID Amount
1 50
2 40
3 50
Table B
ID FormulaID VALUE
X 1+2+3
Y 1-2+3
Result Expectation
ID FormulaID VALUE
X 1+2+3 140
Y 1-2+3 60
由于
答案 0 :(得分:0)
我根据@Ashwin Nair的评论累了这个..这很好..
DECLARE @count INT = 1
DECLARE @Formula VARCHAR(200)
,@FormulaID VARCHAR(100)
,@IDstring VARCHAR(20)
,@operator VARCHAR(1)
CREATE TABLE #temp (RowID INT IDENTITY(1, 1),FormulaID VARCHAR(100),ID INT,SignOper VARCHAR(1),FORMULA VARCHAR(100),Flag INT,VALUE INT)
WHILE ( SELECT COUNT(*)FROM formulaT) >= @count
BEGIN
--Total formula records
SET @Formula = (SELECT formulaID FROM (SELECT ROW_NUMBER() OVER (ORDER BY ID) RowID,*FROM formulaT) a WHERE RowID = @count)
SET @FormulaID = (SELECT ID FROM (SELECT ROW_NUMBER() OVER (ORDER BY ID) RowID,* FROM formulaT) a WHERE RowID = @count)
DECLARE @ID INT
SET @ID = PATINDEX('%[^0-9]%', @Formula)
BEGIN
WHILE @ID > 0
BEGIN
--spliting a formula --ID based on the charactors
SET @IDstring = SUBSTRING(@Formula, 1, @ID - 1)
SET @operator = SUBSTRING(@Formula, @ID, 1)
SET @Formula = REPLACE(@Formula, @IDstring + @operator, '')
INSERT INTO #temp
SELECT @FormulaID,CAST(@IDstring AS INT),@operator,(SELECT CAST(Amount AS VARCHAR) FROM amtt
WHERE Id = CAST(@IDstring AS INT)),0,0
SET @ID = PATINDEX('%[^0-9]%', @Formula)
SET @IDstring = NULL
END
INSERT INTO #temp
SELECT @FormulaID
,@Formula
,''
,(SELECT CAST(Amount AS VARCHAR)
FROM amtt
WHERE Id = CAST(@Formula AS INT))
,0,0
--spliting a formula --ID based on the charactors
END
DECLARE @RowNo INT = (SELECT MIN(RowID) FROM #temp WHERE FormulaID = @FormulaID)
SET @formula = ''
WHILE (SELECT MAX(RowID)FROM #temp WHERE FormulaID = @FormulaID) >= @RowNo
BEGIN
SET @formula = @formula + (SELECT ISNULL(FORMULA + SignOper, SignOper) FROM #temp WHERE FormulaID = @FormulaID AND RowID = @RowNo)
SET @RowNo = @RowNo + 1
END
INSERT INTO #temp
SELECT @FormulaID
,0,'',@formula,1,0
DECLARE @QUERY VARCHAR(250) = (SELECT 'sp_executesql N' + '''select ' + @formula + '''')
CREATE TABLE #CALC (VAL INT)
PRINT @QUERY
INSERT INTO #CALC
EXEC (@QUERY)
INSERT INTO #temp
SELECT @FormulaID
,0,'',@formula,2,(SELECT val FROM #CALC )
DROP TABLE #CALC
SET @Count = @count + 1
END
SELECT F.ID
,F.FORMULAID
,FORMULA
,VALUE
FROM formulaT F
INNER JOIN #temp T ON T.FORMULAID = F.ID
AND T.FLAG = 2
DROP TABLE #temp
--Output
--ID FORMULAID FORMULA VALUE
--X 1+2+3 50+40+50 140
--Y 1-2+3 50-40+50 60
--Please let me know this answer is helpful or not..
由于 KARTHIK
答案 1 :(得分:0)
我认为,你的数据库设计是错误的。你真正的要求是什么,这会引导你考虑上面的数据库设计。你应该抛出更多的背景,你会在这个社区得到非常专业的解决方案。
我尝试了一些东西,只需测试其他样本数据并提供反馈。
DECLARE @TableB table(ID VARCHAR(50),FormulaID VARCHAR(50) ,VALUE INT)
INSERT INTO @TableB VALUES('X','1+2+3',NULL),('Y','1-2+3',NULL)
DECLARE @TableA table (ID INT,Amount INT)
INSERT INTO @TableA values(1,50 ),(2,40 ),(3,50 )
declare @input varchar(50)='a+b-c*d'
declare @delimiter varchar(50)='-+/*'
;WITH CTE
AS (
SELECT id
,CASE
WHEN PATINDEX('%[' + @delimiter + ']%', FormulaID) > 0
THEN substring(FormulaID, 0, PATINDEX('%[' + @delimiter + ']%', FormulaID))
END numbers
,CASE
WHEN PATINDEX('%[' + @delimiter + ']%', FormulaID) > 0
THEN substring(FormulaID, PATINDEX('%[' + @delimiter + ']%', FormulaID), 1)
END delimeter
,CASE
WHEN PATINDEX('%[' + @delimiter + ']%', FormulaID) > 0
THEN stuff(FormulaID, 1, PATINDEX('%[' + @delimiter + ']%', FormulaID), '')
END input
,1 RN
,FormulaID
FROM @TableB
UNION ALL
SELECT id
,CASE
WHEN PATINDEX('%[' + @delimiter + ']%', input) > 0
THEN cast(substring(input, 0, PATINDEX('%[' + @delimiter + ']%', input)) AS VARCHAR(50))
ELSE cast(input AS VARCHAR(50))
END
,CASE
WHEN PATINDEX('%[' + @delimiter + ']%', input) > 0
THEN substring(input, PATINDEX('%[' + @delimiter + ']%', input), 1)
END
,CASE
WHEN PATINDEX('%[' + @delimiter + ']%', input) > 0
THEN stuff(input, 1, PATINDEX('%[' + @delimiter + ']%', input), '')
END
,RN + 1
,FormulaID
FROM cte
WHERE len(input) > 0
)
,CTE1
AS (
SELECT c.id
,c.numbers
,a.amount
,c.delimeter
,rn
,FormulaID
FROM CTE C
INNER JOIN @tableA a ON c.numbers = a.id
)
,CTE4
AS (
SELECT id
,formulaid
,amount
,delimeter
,numbers
,rn
FROM cte1
WHERE rn = 1
UNION ALL
SELECT a.id
,b.formulaid
,CASE
WHEN b.delimeter = '+'
THEN b.amount + a.amount
WHEN b.delimeter = '-'
THEN b.amount - a.amount
WHEN b.delimeter = '*'
THEN b.amount * a.amount
END
,a.delimeter
,a.numbers
,a.RN
FROM cte1 a
INNER JOIN cte4 b ON a.id = b.id
WHERE a.rn = b.rn + 1
)
SELECT id
,formulaid
,amount
FROM cte4
WHERE delimeter IS NULL