How to substract two Sums in Maple - sum

I've got two sequences with variable boundaries like
> a:=Sum(x(i),i=n..m);
> b:=Sum(x(i),i=n-1..m+1);
n and m are arbitrary natural numbers and obviously m>n.
I want to substract a from b and see how Maple simplifies the expression to
> b-a;
x(n-1)+x(m+1);
Is it possible in Maple or in another CAS?

You might do it by using a temporary object,and then acting in two stages.
a:=Sum(x(i),i=n..m):
b:=Sum(x(i),i=n-1..m+1):
temp := Sum(x(i),i=op(1,rhs(op(2,a)))..op(2,rhs(op(2,b))));
m + 1
-----
\
)
/ x(i)
-----
i = n
value( combine(b-temp) + combine(temp-a) );
x(n - 1) + x(m + 1)
Or you might put that into a procedure.
combminus:=proc(s::specfunc(anything,Sum),t::specfunc(anything,Sum))
local temp;
if op(1,s) = op(1,t) then
temp:=Sum(op(1,s),i=op(1,rhs(op(2,s)))..op(2,rhs(op(2,t))));
value(combine(s-temp)+combine(temp-t));
else
s-t;
end if;
end proc:
combminus(b, a);
x(n - 1) + x(m + 1)

Related

postgres access a cte inside a view

is it possible, in postgresql - to access a cte defined in a view?
By that I mean - if you have the following:
create view my_view as
with
blah as (select 1 as x, 2 as y, 3 as z)
select
x*x as x_squared,
y*y as y_squared,
z*z as z_squared
from
blah
is there any way from outside of getting at blah? eg looking for something like:
select * from my_view.blah
Basically we have large views that use a number of complicated CTE's - and it's quite difficult sometimes to troubleshoot them without splitting them all out into separate smaller views [yes, I would prefer to just keep it like that, but I don't have that option]
I know I will be able to do it by making a stored proc that pulls out the view definition - extracts the with clauses, parses up to the blah definition, changes that to the main select, gets rid of the rest, and then does the query - but that all seems like a lot of work. Am hoping there's a built-in way?
You can create the CTE as a view by itself. For example:
create table a (b int);
insert into a (b) values (1), (50), (200), (350), (1000);
create view blah as
select * from a where b > 100;
Anf then base your original view on this new intermediate one to avoid repeating code:
create view my_view as
select * from blah where b < 500;
See running example at DB Fiddle.
ok - so I have a sort of solution - it's a not a function - it's a procedure that turns a cte into a materialized_view.
I first wanted to formulate it as function, so you could say:
select * from cte_from( 'my_real_view', 'the_cte' )
but it appears that a function needs its schema defined in advance, which is obviously impossible in this case. If anyone can suggest a hack to make it closer to above, I'd apperciate it. But anyway - bottom line this works:
create procedure from_cte(view_schema text, view_name text, cte_name text, materialized_view_name text) as
$func$
declare
_code text;
_others text;
_script text;
begin
execute format('drop materialized view if exists %s', materialized_view_name);
with recursive
string_provider as (
select view_definition as the_string,
position(concat(cte_name, ' as (') in lower(view_definition)) + length(cte_name) + 5 as start_location
from information_schema.views
where table_name = view_name
and table_schema = view_schema
),
string_walk as (
select start_location as x,
1 as brackets
from string_provider
union
select x + 1,
new_brackets
from string_provider,
string_walk,
lateral (select case
when substring(the_string from x + 1 for 1) = '(' then brackets + 1
when substring(the_string from x + 1 for 1) = ')' then brackets - 1
else brackets
end as new_brackets
) calculated
where new_brackets != 0
and x < length(the_string)
)
select substring(the_string from start_location for 1 + max(x) - start_location),
trim(substring(the_string from 0 for start_location - length(cte_name) - 5))
into _code, _others
from string_walk,
string_provider
group by the_string, start_location;
if length(_others) < 5 then
select _code into _script;
else
select concat(substring(_others from 0 for length(_others)), ' ', _script) into _script;
end if;
execute format('create materialized view %s as ( %s )', materialized_view_name, _code);
end
$func$ language plpgsql;

How to use two columns with clause definescore oracle text

I have this code:
declare
sName varchar(25);
iRank number := 0;
sDesc varchar(510);
cursor q is
SELECT *
FROM trec_topics ORDER BY num;
BEGIN
for ql in q
loop
sDesc := replace(replace(replace(ql.title, '?', '{?}'), ')', '{)}'), '(', '{(}');
--dbms_output.put_line(ql.num||'-'||sDesc);
declare
cursor c is
SELECT /*+ FIRST_ROWS(100) */ docno,
CASE
WHEN SCORE(10) >= SCORE(20) THEN SCORE(10)
ELSE SCORE(20)
END AS SCORE
FROM txt_search_docs WHERE CONTAINS(txt, 'DEFINESCORE(ql.title, OCCURRENCE)', 10) > 0 OR
CONTAINS(txt, 'DEFINESCORE(sDesc, OCCURRENCE)', 20) > 0
order by SCORE desc;
begin
iRank := 1;
for c1 in c
loop
dbms_output.put_line(ql.num||' Q0 '||c1.docno||' '||lpad(iRank,3, '0')||' '||lpad(c1.score, 2, '0')||' myUser');
iRank := iRank + 1;
exit when c%rowcount = 100;
end loop;
end;
end loop;
end;
As you can see I'm doing select on two different tables, however, I need to change the standard score, as it did not perform well. I'm trying to use the DEFINESCORE clause that has this 'DEFINESCORE (query_term, scoring_expression)' format.
How can I call the table columns within this clause? That is, I need to call my columns instead of "query_term", as there are several documents to do the search. Because the way I’m calling him, he’s looking for exactly the term ql.title
Anyone a suggestion to help me with this problem?
I finally managed to solve it.
It was about:
create a variable: topics varchar (525);
store the column value: topics := replace(replace(replace(ql.title, '?', '{?}'), ')', '{)}'), '(', '{(}');
and after calling it in the CONTAINS clause: FROM txt_search_docs WHERE CONTAINS(txt, 'DEFINESCORE(('''||topics||'''), OCCURRENCE)', 1) > 0

How to use variable in an sql statement when the variables have special characters

I am attempting to select columns of data from several different tables in a for loop, and each of the table names begin with numbers, titled 0_training_market through 155_training_market.
To use a table beginning with a number in an sql statement, I have to use an extra pair of quotations around that title, which just turns my variable into a string and doesn't read the actual variable. Here is my code and error:
for j in list(range(156)):
generation = str(j)+'_training_market'
energy_source = db.query(" SELECT energy_source FROM " + generation + " WHERE id < 100 ORDER BY id ")
quantity = db.query(" SELECT quantity FROM " + generation + " WHERE id < 100 ORDER BY id ")
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.SyntaxError) syntax error at or near "0"
LINE 1: SELECT energy_source FROM 0_training_market WHERE id < 100 ...
^
[SQL: SELECT energy_source FROM 0_training_market WHERE id < 100 ORDER BY id ]
I'm not sure how to work around this, so any help is appreciated. Thanks
PostgreSQL needs to have doublequotes around badly named objects:
for j in list(range(156)):
generation = str(j)+'_training_market'
energy_source = db.query(""" SELECT energy_source FROM "{}" WHERE id < 100 ORDER BY id """.format(generation))
quantity = db.query(""" SELECT quantity FROM "{}" WHERE id < 100 ORDER BY id """.format(generation))

Divide by zero error in SQL even though I excluded the zero cases?

Here is the code that I've been trying to run:
SELECT C.* FROM
(SELECT
B.[OUTSIDE_ROW],
B.[INSIDE_ROW],
B.[r_HU_vac_ns],
B.[r_HU_vac_ns_MOE],
CASE WHEN B.[r_HU_vac_ns] = 0 THEN 999 ELSE B.[r_HU_vac_ns_MOE]/B.[r_HU_vac_ns] END AS [PCT]
FROM
(SELECT
A.[OUTSIDE_ROW],
A.[INSIDE_ROW],
(A.[HU_VACANT] - A.[HU_VACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT] AS [r_HU_vac_ns],
(1/A.[HU_VACANT]) * POWER(
CASE WHEN ((A.[HU_VACANT] - A.[HU_VACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT]) * POWER(A.[HU_VACANT_MOE], 2) < POWER(A.[HU_VACANT_MOE], 2) + POWER(A.[HU_VACANT_SEASONAL_RECREATIONAL_MOE], 2) THEN POWER(A.[HU_VACANT_MOE], 2) + POWER(A.[HU_VACANT_SEASONAL_RECREATIONAL_MOE], 2) - (((A.[HU_VACANT] - A. [HU_vACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT]) * POWER(A.[HU_VACANT_MOE], 2))
ELSE POWER(A.[HU_VACANT_MOE], 2) + POWER(A. [HU_VACANT_SEASONAL_RECREATIONAL_MOE], 2) + (((A.[HU_VACANT] - A. [HU_vACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT]) * POWER(A.[HU_VACANT_MOE], 2)) END, 0.5) AS [r_HU_vac_ns_MOE]
FROM
(SELECT
[OUTSIDE_ROW],
[INSIDE_ROW],
SUM([ESTIMATE_1]) AS [HU_VACANT],
POWER(SUM(POWER([MOE_1], 2)), 0.5) AS [HU_VACANT_MOE],
SUM([ESTIMATE_2]) AS [HU_VACANT_SEASONAL_RECREATIONAL],
POWER(SUM(POWER([MOE_2], 2)), 0.5) AS [HU_VACANT_SEASONAL_RECREATIONAL_MOE]
FROM #TEST_TABLE
GROUP BY [OUTSIDE_ROW], [INSIDE_ROW]) A
WHERE A.[HU_VACANT] > 0) B ) C
WHERE C.[PCT] < 0.2
Every time I run it, I get the following error:
Msg 8134, Level 16, State 1, Line 533
Divide by zero error encountered.
However, if I take off the last line of code (the following WHERE clause) the code runs fine:
WHERE C.[PCT] < 0.2
Just from looking at my query, can anyone tell me what I'm doing wrong? I thought I eliminated all PCT values that were zero with the CASE WHEN statement below so this error is baffling me:
CASE WHEN B.[r_HU_vac_ns] = 0 THEN 999 ELSE B.[r_HU_vac_ns_MOE]/B.[r_HU_vac_ns] END AS [PCT]
If it helps, PCT is cast as floating point.
Thanks.
SQL Server reserves the right to rearrange calculations. That means that the calculation in a SELECT can happen before filtering occurs. This is true even when the filters are in subqueries and CTEs.
The only way to guarantee order of calculation is CASE. However, I think it is easier to just use NULLIF(), an ANSI standard function. Instead of logic like this:
(A.[HU_VACANT] - A.[HU_VACANT_SEASONAL_RECREATIONAL])/A.[HU_VACANT] AS [r_HU_vac_ns],
do:
(A.[HU_VACANT] - A.[HU_VACANT_SEASONAL_RECREATIONAL])/NULLIF(A.[HU_VACANT], 0) AS [r_HU_vac_ns],
Instead of filtering out the records using
WHERE A.[HU_VACANT] > 0
You should filter out the records at root level
having SUM([ESTIMATE_1]) > 0
You could also use nullif function but that will result producing NULL where you have zero

Splitting a Path Enumeration Model PathString in MySQL

I'm trying to implement a Path Enumeration model as per Joe Celko's book (page 38). The relevant attributes of my table (and the support table that just contains sequential integers) look like this:
Contribution
------------
ContributionID
PathString
_IntegerSeries
--------------
IntegerID
_IntegerSeries contains integers 1 to n where n is bigger than I'll ever need. Contribution contains three records:
1 1
2 12
3 123
... and I use a modified version of Joe's query:
SELECT SUBSTRING( c1.PathString
FROM (s1.IntegerID * CHAR_LENGTH(c1.ContributionID))
FOR CHAR_LENGTH(c1.ContributionID)) AS ContID
FROM
Contribution c1, _IntegerSeries s1
WHERE
c1.ContributionID = 3
AND s1.IntegerID <= CHAR_LENGTH(c1.PathString)/CHAR_LENGTH(c1.ContributionID);
... to successfully return a result set containing all of ContributionID 3's superiors in the hierarchy. Now, in this example, the PathString column holds plain integer values and obviously we run into trouble once we hit ContributionID 10. So we modify the PathString column to include separators:
1 1.
2 1.2.
3 1.2.3.
Now... the book doesn't give an example of getting superiors when the PathString uses delimiters... so I'll have to figure that out later. But it does give an example for how to split up a PathString (which I'm guessing is going to help me do superior searches). The MySQL version of the example code to do this is:
SELECT SUBSTRING( '.' || c1.PathString || '.'
FROM s1.IntegerID + 1
FOR LOCATE('.', '.' || c1.PathString || '.', s1.IntegerID + 1) - s1.IntegerID - 1) AS Node
FROM _IntegerSeries s1, Contribution c1
WHERE
SUBSTRING('.' || c1.PathString || '.' FROM s1.IntegerID FOR 1) = '.'
AND IntegerID < CHAR_LENGTH('.' || c1.PathString || '.');
... but this code returns an empty result set. I'm doing something wrong, but I'm not sure what. Figured I'd put this out to the stackoverflow community prior to bothering Joe with an email. Anyone have any thoughts?
UPDATE
Quassnoi's query... slightly modified a bit after testing, but exactly the same as his original functionally. Very nice. Much cleaner than what I was using. Big thanks.
SET #contributionID = 3;
SELECT ca.*
FROM
Contribution c INNER JOIN _IntegerSeries s
ON s.IntegerID < #contributionID AND SUBSTRING_INDEX(c.PathString, '.', s.IntegerID) <> SUBSTRING_INDEX(c.PathString, '.', s.IntegerID + 1)
INNER JOIN Contribution ca
ON ca.PathString = CONCAT(SUBSTRING_INDEX(c.PathString, '.', s.IntegerID), '.')
WHERE c.ContributionID = #contributionID;
This is because || in MySQL is boolean OR, not string concatenation.
To find all ancestors of a given Contribution, use:
SELECT ca.*
FROM Contribution с
JOIN IntegerSeries s
ON IntegerID < CHAR_LENGTH(c.path)
AND SUBSTRING_INDEX(c.path, '.', IntegerID) <> SUBSTRING_INDEX(c.path, '.', IntegerID + 1)
JOIN Contribution ca
ON ca.path = CONCAT(SUBSTRING_INDEX(c.path, '.', IntegerID), '.')
WHERE c.ContributionID = 3