On my example below, I am using sqlalchemy orm to update the values of a column (column_2) conditional to the values of another column (column_1).
I am currently using two updates to achieve that.
Is it possible to combine these two updates into one? That would save the second execute on my code below.
update_1 = update(table).where(table.c[column_1] != "ABC").values({table.c[column_2]:(table.c[column_3] * table.c[column_4]) })
db.execute(update_1)
update_2 = update(table).where(table.c[column_1] == "ABC").values({table.c[column_2]:table.c[column_3] })
db.execute(update_2)
Related
Suppose I want to add 3 columns (A,B,C) to an existing dataframe. Each column requires some processing on the existing dataframe. Also the processing has to be done on a group of rows defined by a column 'code'.
So my question is which is faster
df.groupby('code').apply(generate_A)
df.groupby('code').apply(generate_B)
df.groupby('code').apply(generate_C)
or
df.groupby('code').apply(generate_A_B_C)
where generate_A_B_C is a function which calls generate_A, generate_B, generate_C on the group defined by 'code'.
df['rsi_1_increases_above_lower_threshold_Close'] = df.groupby('SecuritiesCode').apply(detect_if_RSI_crosses_above_lower_threshold,
rsi_lower_threshold = rsi_lower_threshold,
rsi_column='rsi_1_Close')
df['rsi_1_decreases_below_upper_threshold_Close'] = df.groupby('SecuritiesCode').apply(detect_if_RSI_crosses_below_upper_threshold,
rsi_upper_threshold = rsi_upper_threshold,
rsi_column='rsi_1_Close')
This question already has answers here:
sqlalchemy filter multiple columns
(4 answers)
Closed last year.
I have an Orders table. And I want to write a query to this table with more than one condition. For example, I want to get an order with id field 1 and order_status field 3.
Is there a way to do this with SQL Alchemy?
P.S. I am able to check only one condition with the following query.
order = Orders.query.filter_by(restaurant_id = restaurant_id).all()
There are multiple ways of doing this for example if you want to apply an and operation you can simply use filter chain as below
order = Orders.query.filter(restaurant_id = restaurant_id).filter(id = 1).filter(order_status = "Status").all()
You can also use and_ and or_ to apply respective conditions like below.
cond = and_(restaurant_id = restaurant_id, id = 1)
order = Orders.query.filter(or_(cond, order_status = "Status")).all()
I'm trying to the convert the below DataFrame into Series:
The columns "Emerging Markets" and "Event Driven" are of interest to me. So, I create a new DataFrame by using the code below:
columns = ['Emerging Markets','Event Driven'] #Indicate which columns I want to use
TargetData = Hedgefunds[columns]
But now I want to create two series, one for "Emerging Markets" and one for "Event Driven" but I'm can't figure out how to do it. I used the code below (same logic as above) but it does not work:
Emerging_Markets_Column = ['Emerging Markets']
EM = TargetData['Emerging_Markets-Column']
What would be the best way to go about separating the columns from each other?
Why dont you use the first dataframe as reference and try .
EM = Hedgefunds['Emerging Markets']
ED = Hedgefunds['Event Driven']
SUMMARY:
How to query against values from different data frame columns with table.column_name combinations in SQL Alchemy using the OR_ statement.
I'm working on a SQL Alchemy project where I pull down valid columns of a dataframe and enter them all into SQL Alchemy's filter. I've successfully got it running where it would enter all entries of a column using the head of the column like this:
qry = qry.filter(or_(*[getattr(Query_Tbl,column_head).like(x) \
for x in (df[column_head].dropna().values)]))
This produced the pattern I was looking for of (tbl.column1 like a OR tbl.column1 like b...) AND- etc.
However, there are groups of the dataframe that need to be placed together where the columns are different but still need to be placed within the OR_ category,
i.e. (The desired result)
(tbl1.col1 like a OR tbl.col1 like b OR tbl.col2 like c OR tbl.col2 like d OR tbl.col3 like e...) etc.
My latest attempt was to sub-group the columns I needed grouped together, then repeat the previous style inside those groups like:
qry = qry.filter(or_((*[getattr(Query_Tbl, set_id[0]).like(x) \
for x in (df[set_id[0]].dropna().values)]),
(*[getattr(Query_Tbl, set_id[1]).like(y) \
for y in (df[set_id[1]].dropna().values)]),
(*[getattr(Query_Tbl, set_id[2]).like(z) \
for z in (df[set_id[2]].dropna().values)])
))
Where set_id is a list of 3 strings corresponding to column1, column2, and column 3 so I get the designated results, however, this produces simply:
(What I'm actually getting)
(tbl.col1 like a OR tbl.col1 like b..) AND (tbl.col2 like c OR tbl.col2 like d...) AND (tbl.col3 like e OR...)
Is there a better way to go about this in SQL Alchemy to get the result I want, or would it better to find a way of implementing column values with Pandas directly into getattr() to work it into my existing code?
Thank you for reading and in advance for your help!
It appears I was having issues with the way the data-frame was formatted, and I was reading column names into groups differently. This pattern works for anyone who want to process multiple df columns into the same OR statements.
I apologize for the issue, if anyone has any comments or questions on the subject I will help others with this type of issue.
Alternatively, I found a much cleaner answer. Since SQL Alchemy's OR_ function can be used with a variable column if you use Python's built in getattr() function, you only need to create (column,value) pairs where by you can unpack both in a loop.
for group in [group_2, group_3]:
set_id = list(set(df.columns.values) & set(group))
if len(set_id) > 1:
set_tuple = list()
for column in set_id:
for value in df[column].dropna().values:
set_tuple.append((column, value))
print(set_tuple)
qry = qry.filter(or_(*[getattr(Query_Tbl,id).like(x) for id, x in set_tuple]))
df = df.drop(group, axis=1)
If you know what column need to be grouped in the Or_ statement, you can put them into lists and iterate through them. Inside those, you create a list of tuples where you create the (column, value) pairs you need. Then within the Or_ function you upact the column and values in a loop, and assign them accordingly. The code is must easier to read and much for compack. I found this to be a more robust solution than explicitly writing out cases for the group sizes.
Is it possible to do SELECT * in SQLAlchemy?
Specifically, SELECT * WHERE foo=1?
Is no one feeling the ORM love of SQLAlchemy today? The presented answers correctly describe the lower-level interface that SQLAlchemy provides. Just for completeness, this is the more-likely (for me) real-world situation where you have a session instance and a User class that is ORM mapped to the users table.
for user in session.query(User).filter_by(name='jack'):
print(user)
# ...
And this does an explicit select on all columns.
The following selection works for me in the core expression language (returning a RowProxy object):
foo_col = sqlalchemy.sql.column('foo')
s = sqlalchemy.sql.select(['*']).where(foo_col == 1)
If you don't list any columns, you get all of them.
query = users.select()
query = query.where(users.c.name=='jack')
result = conn.execute(query)
for row in result:
print row
Should work.
You can always use a raw SQL too:
str_sql = sql.text("YOUR STRING SQL")
#if you have some args:
args = {
'myarg1': yourarg1
'myarg2': yourarg2}
#then call the execute method from your connection
results = conn.execute(str_sql,args).fetchall()
Where Bar is the class mapped to your table and session is your sa session:
bars = session.query(Bar).filter(Bar.foo == 1)
Turns out you can do:
sa.select('*', ...)
I had the same issue, I was trying to get all columns from a table as a list instead of getting ORM objects back. So that I can convert that list to pandas dataframe and display.
What works is to use .c on a subquery or cte as follows:
U = select(User).cte('U')
stmt = select(*U.c)
rows = session.execute(stmt)
Then you get a list of tuples with each column.
Another option is to use __table__.columns in the same way:
stmt = select(*User.__table__.columns)
rows = session.execute(stmt)
In case you want to convert the results to dataframe here is the one liner:
pd.DataFrame.from_records(rows, columns=rows.keys())
For joins if columns are not defined manually, only columns of target table are returned. To get all columns for joins(User table joined with Group Table:
sql = User.select(from_obj(Group, User.c.group_id == Group.c.id))
# Add all coumns of Group table to select
sql = sql.column(Group)
session.connection().execute(sql)
I had the same issue, I was trying to get all columns from a table as a list instead of getting ORM objects back. So that I can convert that list to pandas dataframe and display.
What works is to use .c on a subquery or cte as follows:
U = select(User).cte('U')
stmt = select(*U.c)
rows = session.execute(stmt)
Then you get a list of tuples with each column.
Another option is to use __table__.columns in the same way:
stmt = select(*User.__table__.columns)
rows = session.execute(stmt)
In case you want to convert the results to dataframe here is the one liner:
pd.DataFrame.from_records(dict(zip(r.keys(), r)) for r in rows)
If you're using the ORM, you can build a query using the normal ORM constructs and then execute it directly to get raw column values:
query = session.query(User).filter_by(name='jack')
for cols in session.connection().execute(query):
print cols
every_column = User.__table__.columns
records = session.query(*every_column).filter(User.foo==1).all()
When a ORM class is passed to the query function, e.g. query(User), the result will be composed of ORM instances. In the majority of cases, this is what the dev wants and will be easiest to deal with--demonstrated by the popularity of the answer above that corresponds to this approach.
In some cases, devs may instead want an iterable sequence of values. In these cases, one can pass the list of desired column objects to query(). This answer shows how to pass the entire list of columns without hardcoding them, while still working with SQLAlchemy at the ORM layer.