Solution to TSQL Challenge 48 - Parse and evaluate Arithmetic Expressions using TSQL By durk
;WITH C (id, expr, v, q, s, x, r, t, w, l, i, n)
AS (SELECT id,
expr,
x0 + (dx * n),
CAST ('' AS VARCHAR (8000)),
CAST ('' AS VARCHAR (8000)),
CAST ('' AS VARCHAR (8000)),
CAST ('' AS VARCHAR (8000)),
'(',
REPLACE(expr, ' ', '') + ')',
0,
0,
CAST (0 AS FLOAT (53))
FROM Tsqlc_Tally AS t WITH (NOLOCK)
INNER JOIN
TC48 AS c WITH (NOLOCK)
ON t.N < c.points
UNION ALL
SELECT id,
expr,
v,
q + CASE t WHEN '^' THEN LEFT(s, PATINDEX('%[(*/+--]%', s) - 1) WHEN '*' THEN LEFT(s, PATINDEX('%[(+--]%', s) - 1) WHEN '/' THEN LEFT(s, PATINDEX('%[(+--]%', s) - 1) WHEN '+' THEN LEFT(s, CHARINDEX(CHAR(40), s) - 1) WHEN '-' THEN LEFT(s, CHARINDEX(CHAR(40), s) - 1) WHEN ')' THEN LEFT(s, CHARINDEX(CHAR(40), s) - 1) WHEN '(' THEN '' WHEN '' THEN '' WHEN 'X' THEN CAST (V AS VARCHAR (8000)) + CHAR(32) ELSE t + ' ' END,
CASE ASCII(t) WHEN 94 THEN '^ ' + SUBSTRING(s, PATINDEX('%[(*/+--]%', s), l) WHEN 42 THEN '* ' + SUBSTRING(s, PATINDEX('%[(+--]%', s), l) WHEN 47 THEN '/ ' + SUBSTRING(s, PATINDEX('%[(+--]%', s), l) WHEN 43 THEN '+ ' + SUBSTRING(s, CHARINDEX(CHAR(40), s), l) WHEN 45 THEN '- ' + SUBSTRING(s, CHARINDEX(CHAR(40), s), l) WHEN 40 THEN '( ' + s WHEN 41 THEN SUBSTRING(s, CHARINDEX(CHAR(40), s) + 2, l) ELSE s END,
SUBSTRING(q, i + 1, NULLIF (CHARINDEX(CHAR(32), q, i + 1), 0) - i - 1),
CASE WHEN x IS NULL THEN r WHEN CHARINDEX(x, '*/+-^') = 0 THEN CONVERT(VARCHAR(8000), n, 2) + CHAR(32) + r ELSE RIGHT(r, 1 + LEN(r) - CHARINDEX(CHAR(32), r)) END,
LEFT(w, 1),
LTRIM(SUBSTRING(w, 2, LEN(w))),
LEN(s),
ISNULL(NULLIF (CHARINDEX(CHAR(32), q, i + 1), 0), DATALENGTH(q)),
n = CASE ISNULL(x, '') WHEN '' THEN n WHEN '^' THEN POWER(CAST (LEFT(r, CHARINDEX(CHAR(32), r)) AS FLOAT (53)), n) WHEN '*' THEN CAST (LEFT(r, CHARINDEX(CHAR(32), r)) AS FLOAT (53)) * n WHEN '/' THEN CAST (LEFT(r, CHARINDEX(CHAR(32), r)) AS FLOAT (53)) / n WHEN '+' THEN CAST (LEFT(r, CHARINDEX(CHAR(32), r)) AS FLOAT (53)) + n WHEN '-' THEN CAST (LEFT(r, CHARINDEX(CHAR(32), r)) AS FLOAT (53)) - n ELSE cast(x as float(53)) END
FROM C
WHERE NOT (t = ''
AND x IS NULL))
SELECT expr,
v AS x,
n AS value
FROM C
WHERE t = ''
AND x IS NULL
ORDER BY expr, v
OPTION (MAXRECURSION 0);
Sr# StartTime Reads Writes CPU Duration
--- ------------------- ----------- ----------- ----------- --------
1 Mar 26 2011 2:21PM 974098 75 4203 4.308
2 Mar 26 2011 2:23PM 974077 75 4110 4.292
3 Mar 26 2011 2:24PM 974077 75 4140 4.292
4 Mar 26 2011 2:25PM 974087 76 4078 4.281
5 Mar 26 2011 2:26PM 974087 76 4094 4.293