2016-06-14 4 views
1

私は動的にクエリを作成するためにあなたの助けが必要です 他のテーブルの数式からデータ値を取り込む方法。 @Ashwinナイールのcomment..itが正常に動作に基づいて、この私がうんざりSQLクエリの動的に式を使用する方法?

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

フロントエンドではもっと使いやすいかもしれないので、どのフロントエンドを使用していますか? 'テーブルA 'のレコードの数は固定されているか、少なくとも10未満ですか?操作の数は+と - に制限されていますか?ストアドプロシージャを使用していますか? – Ash

+0

こんにちは、あなたのお返事ありがとうございます。それはフロントエンドで簡単かもしれませんが、私は店の手順でこれを処理します:)。テーブルAのレコード数は固定されておらず、10を超えることができ、演算は+と - だけでなく、(1 * 2) - (3 + 1)のようになります。 –

+0

これを行う直接的な方法はないようですが、あなたはSPでも問題ないので、問題を分解してください:.....最初に[Table B]からFormulaIdを選択し、レコードをループして番号を取得してください'(+、 - 、*、/、(、))を' array'の中で検索しながら 'substring'を使うことで、文字列を出力することができます。配列の各要素に対して、[Table A]からId = ... 'の量を選択します。実際の値を含む文字列を取得したら、基本的に式を実行するために 'exec'を使います。 – Ash

答えて

0

以下

サンプル..

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.. 

おかげ カルティク

0

私は思いますあなたのDBデザインは間違っています上記のDBデザインについて考えてみてください。あなたは少しだけ背景を投げてください。あなたはこのコミュニティで非常にプロフェッショナルなソリューションを得るでしょう。

私は何か試しただけで、他のサンプルデータでテストし、フィードバックを与えます。

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 
関連する問題