How to implement slicing in docplex? - docplex

I'm transferring some code from OPL to docplex and I'm having troubles with the syntax for slicing. I'm attempting to create a set of constraints with a summation over all values with connection to another decision variable.
I've tried both add_constraints and add_constraint (inside a for loop) but I'm getting an invalid syntax error. I used this format with Google OR so I'd expected this to work.
Here's my OPL code:
forall(<var1,var3> in Index2)
sum(<var1,var2,var3> in Index1)
dev_var[var1,var2,var3] == cec_var2[<var1,var3>];
I tried the following in docplex:
for row2 in df1.itertuples():
solver.add_constraint(solver.sum(dec_var[row.var1,row.var2,row.var3]
for row in df2.itertuples()) == dec_var2[row2.var1,row2.var3]
if row2.var1 = row.var1 and row2.var3 = row.var3)
I'm expecting to create a constraint for each var1,var3 combination that includes all relevant indexes of var1,var2,var3 found in the other index/dataframe. With the "if" statement included, I get a "invalid syntax" error, but without it I get constraints that include a full Cartesian join of the other index without any filtering.

In your if statement, did you try using == (equality operator) instead of = (assignment operator)? I'm not sure that python/pandas like assignments in the conditional expression.

for var1 in index2:
for var3 in index2:
model.add_constraint(model.sum(model.sum(model.sum(dev_var[a,b,c] for a in index1) for b in index1) for c in index1) == cec_var2[var1,var3])
there is something wrong,hope a little help for you

Related

How to create a data frame from another data frame, filter rows and select specific columns all at the same time? [duplicate]

I know this error message has been discussed on here before but I still cannot figure out how to make this work. I'm trying to do a np.where statement with more than one condition. Below is my code. I am getting the error message "Keyword can't be an expression" and it is highlighting the space after "aggregate['Counter'] > 1.
aggregate['1'] = np.where(np.logical_and(aggregate['Counter'] > 1, aggregate['2'].shift(1) = aggregate['3']), 0, aggregate['2'])
The comparison operator is ==, not =:
...aggregate['2'].shift(1) == aggregate['3']),...
^^ here
You need a double equals sign:
aggregate['1'] = np.where(np.logical_and(aggregate['Counter'] > 1, aggregate['2'].shift(1) == aggregate['3']), 0, aggregate['2']

Add conditions where with 2 field conditions do not run accurately

The data that appears does not match the conditions that have been applied
I implemented SQL code in the Navicat application, and have changed the structure of the code several times but it still doesn't work,
data that is not of ilart condition type
still appears
SELECT SERMAT,ILART,sum(GKSTP) as jumlah
FROM swift_zab_iw39
WHERE ILART='OVH' OR ILART='TST' and SERMAT='024147-000:09052'
GROUP BY ILART,SERMAT
Use IN operator:
WHERE ILART IN('OVH','TST') AND SERMAT = '024147-000:09052'
Add parenthesis to the OR condition in the WHERE clause as:
WHERE (ILART = 'OVH' OR ILART = 'TST') AND SERMAT = '024147-000:09052'

Passing Optional List argument from Django to filter with in Raw SQL

When using primitive types such as Integer, I can without any problems do a query like this:
with connection.cursor() as cursor:
cursor.execute(sql='''SELECT count(*) FROM account
WHERE %(pk)s ISNULL OR id %(pk)s''', params={'pk': 1})
Which would either return row with id = 1 or it would return all rows if pk parameter was equal to None.
However, when trying to use similar approach to pass a list/tuple of IDs, I always produce a SQL syntax error when passing empty/None tuple, e.g. trying:
with connection.cursor() as cursor:
cursor.execute(sql='''SELECT count(*) FROM account
WHERE %(ids)s ISNULL OR id IN %(ids)s''', params={'ids': (1,2,3)})
works, but passing () produces SQL syntax error:
psycopg2.ProgrammingError: syntax error at or near ")"
LINE 1: SELECT count(*) FROM account WHERE () ISNULL OR id IN ()
Or if I pass None I get:
django.db.utils.ProgrammingError: syntax error at or near "NULL"
LINE 1: ...LECT count(*) FROM account WHERE NULL ISNULL OR id IN NULL
I tried putting the argument in SQL in () - (%(ids)s) - but that always breaks one or the other condition. I also tried playing around with pg_typeof or casting the argument, but with no results.
Notes:
the actual SQL is much more complex, this one here is a simplification for illustrative purposes
as a last resort - I could alter the SQL in Python based on the argument, but I really wanted to avoid that.)
At first I had an idea of using just 1 argument, but replacing it with a dummy value [-1] and then using it like
cursor.execute(sql='''SELECT ... WHERE -1 = any(%(ids)s) OR id = ANY(%(ids)s)''', params={'ids': ids if ids else [-1]})
but this did a Full table scan for non empty lists, which was unfortunate, so a no go.
Then I thought I could do a little preprocessing in python and send 2 arguments instead of just the single list- the actual list and an empty list boolean indicator. That is
cursor.execute(sql='''SELECT ... WHERE %(empty_ids)s = TRUE OR id = ANY(%(ids)s)''', params={'empty_ids': not ids, 'ids': ids})
Not the most elegant solution, but it performs quite well (Index scan for non empty list, Full table scan for empty list - but that returns the whole table anyway, so it's ok)
And finally I came up with the simplest solution and quite elegant:
cursor.execute(sql='''SELECT ... WHERE '{}' = %(ids)s OR id = ANY(%(ids)s)''', params={'ids': ids})
This one also performs Index scan for non empty lists, so it's quite fast.
From the psycopg2 docs:
Note You can use a Python list as the argument of the IN operator using the PostgreSQL ANY operator.
ids = [10, 20, 30]
cur.execute("SELECT * FROM data WHERE id = ANY(%s);", (ids,))
Furthermore ANY can also work with empty lists, whereas IN () is a SQL syntax error.

R - Using sqldf to query multiple values from one column in dataframe

I'm pretty new to R and trying to use the SQLDF package to query a dataset. I have constructed the following query, which works perfectly and displays the correct data:
sqldf("select AreaName, TimePeriod, Value from df2 where Indicator == 'Obese children (Year 6)' AND AreaName == 'Barking and Dagenham'",
row.names = TRUE)
But I would like to pull the data for 'Richmond upon Thames' as well as Barking and Dagenham. I have tried this:
AND AreaName == 'Barking and Dagenham', 'Richmond upon Thames'
Which gives me the following error:
Error in sqliteSendQuery(con, statement, bind.data) : error in statement: near ",": syntax error
And I have also tried:
AND AreaName == 'Barking and Dagenham' AND AreaName == 'Richmond upon Thames'
Which creates the new dataframe as expected but when I view it, it is empty. I know it is not an issue with the name 'Richmond upon Thames' as I have entered this into the first statement by itself instead of 'Barking and Dagenham' and it works perfectly.
Could anybody help me with what the correct structure should be?
Many thanks

SQL Update on joined tables with calculated fields

First of all, I know there are already questions and answers about it, this thread being the one that is closest to what I need:
SQL Update to the SUM of its joined values
However, I get a syntax error (operator missing) that seems to occur close to the FROM clause. However I can't see it. Does it not like the FROM itself ? I am not used to using FROM in an update statement but it seems like it's valid from the QA I just linked :|
Any idea why there would be a syntax error there ?
I am using Access 2007 SP3.
Edit:
Wow, I forgot to post the query...
UPDATE r
SET
r.tempsmoy_requete_min = tmm.moy_mob_requete
FROM
rapports AS r INNER JOIN
(SELECT
id_fichier,
Round(Sum(temps_requete_min)/3,0) As moy_mob_requete,
Round(Sum(temps_analyse_min)/3,0) As moy_mob_analyse,
Round(Sum(temps_maj_min)/3,0) As moy_mob_maj,
Round(Sum(temps_rap_min)/3,0) As moy_mob_rap,
Round(Sum(temps_ddc_min)/3,0) As moy_mob_ddc
FROM maintenances
WHERE
periode In (10,9,8) And
annee=2011
GROUP BY id_fichier) AS tmm ON rapports.id_rapport = tmm.id_fichier
WHERE
1=0
The WHERE 1=0 part is because I want to test further the subquery before running it.
Edit: This is some simpler query I am trying. I get a different error this time. It now tells me that tempsmoy_requete_min (and probably all other left operands) are not part of an aggregate function... which is the point of my query. Any idea ?
UPDATE
rapports INNER JOIN maintenances ON rapports.id_rapport = maintenances.id_fichier
SET
rapports.tempsmoy_requete_min = Round(Sum(temps_requete_min)/3,0),
rapports.tempsmoy_analyse_min = Round(Sum(temps_analyse_min)/3,0),
rapports.tempsmoy_maj_min = Round(Sum(temps_maj_min)/3,0),
rapports.tempsmoy_rap_min = Round(Sum(temps_rap_min)/3,0),
rapports.tempsmoy_ddc_min = Round(Sum(temps_ddc_min)/3,0)
WHERE
maintenances.periode In (10,9,8) And
maintenances.annee=2011 AND
1=0
I tried adapting your first query sample, and was able to make your error go away. However then I encountered a different error ('Operation must use an updateable query').
It may be possible to overcome that error, too. However, I found it easier to use a domain function instead of a join to retrieve the replacement value.
UPDATE rapports
SET tempsmoy_requete_min = Round(DSum("temps_requete_min",
"maintenances",
"periode In (10,9,8) AND annee=2011 "
& "AND id_fichier='" & id_rapport
& "'")/3, 0);
If this suggestion works for tempsmoy_requete_min with your data, you will have to extend it to the other fields you want to replace. That won't be pretty. You could make it less ugly with a saved query which you then use as the "Domain" parameter for DSum() ... that could allow you to use a simpler "Criteria" parameter.
UPDATE r
should be
UPDATE rapports
You can't reliably use an alias in the update target.