translate from SQL to SQLAlchemy - python

i have the following sql script.
SELECT *
FROM movies
LEFT JOIN possession
ON movies.id = possession.movie_id
AND possession.master_id = ?
WHERE possession.id is NULL
ORDER BY movies.id DESC
and need help to illustrate in sqlalchemy.
Please can someone help me?
The following doesn't work:
movies = movie.Movie.query.join(possession.Possession, movie.Movie.id == possession.Possession.movie_id)\
.filter(possession.Possession.master_id == session.get('userId'))\
.filter(not_(possession.Possession.id)).order_by(movie.Movie.id.desc()).all()
Thank you very much!
Cheers

The most direct way to translate your SQL query is the ORM query below:
qry = (session.query(Movie)
.outerjoin(Possession, and_(Movie.id == Possession.movie_id, Possession.master_id == master_id))
.filter(Possession.id == None)
.order_by(desc(Movie.id))
)
movies = qry.all()
produces:
SELECT movies.id AS movies_id, movies.name AS movies_name
FROM movies LEFT OUTER JOIN possessions ON movies.id = possessions.movie_id AND possessions.master_id = :master_id_1
WHERE possessions.id IS NULL ORDER BY movies.id DESC
I also think this would be the faster implementation compared to an alternative of using any (see below), which is more concise, but the SQL it produces is not. This also assumes there is a relationship Movie.possessions = relationship(Possession):
qry = (session.query(Movie)
.filter(~Movie.possessions.any(Possession.master_id == master_id))
.order_by(desc(Movie.id))
)
movies = qry.all()
produces:
SELECT movies.id AS movies_id, movies.name AS movies_name
FROM movies
WHERE NOT (EXISTS (SELECT 1
FROM possessions
WHERE movies.id = possessions.movie_id AND possessions.master_id = :master_id_1)) ORDER BY movies.id DESC

Related

Peewee: Relation does not exist when querying with CTE

I want to query the count of bookings for a given event- if the event has bookings, I want to pull the name of the "first" person to book it.
The table looks something like: Event 1-0 or Many Booking, Booking.attendee is a 1:1 with User Table. In pure SQL I can easily do what I want by using Window Functions + CTE. Something like:
WITH booking AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY b.event_id ORDER BY b.created DESC) rn,
COUNT(*) OVER (PARTITION BY b.event_id) count
FROM
booking b JOIN "user" u on u.id = b.attendee_id
WHERE
b.status != 'cancelled'
)
SELECT e.*, a.vcount, a.first_name, a.last_name FROM event e LEFT JOIN attendee a ON a.event_id = e.id WHERE (e.seats > COALESCE(a.count, 0) and (a.rn = 1 or a.rn is null) and e.cancelled != true;
This gets everything I want. When I try to turn this into a CTE and use Peewee however, I get errors about: Relation does not exist.
Not exact code, but I'm doing something like this with some dynamic where clauses for filtering based on params.
cte = (
BookingModel.select(
BookingModel,
peewee.fn.ROW_NUMBER().over(partition_by=[BookingModel.event_id], order_by=[BookingModel.created.desc()]).alias("rn),
peewee.fn.COUNT(BookingModel.id).over(partition_by=[BookingModel.event_id]).alias("count),
UserModel.first_name,
UserModel.last_name
)
.join(
UserModel,
peewee.JOIN.LEFT_OUTER,
on(UserModel.id == BookingModel.attendee)
)
.where(BookingModel.status != "cancelled")
.cte("test")
query = (
EventModel.select(
EventModel,
UserModel,
cte.c.event_id,
cte.c.first_name,
cte.c.last_name,
cte.c.rn,
cte.c.count
)
.join(UserModel, on=(EventModel.host == UserModel.id))
.switch(EventModel)
.join(cte, peewee.JOIN.LEFT_OUTER, on=(EventModel.id == cte.c.event_id))
.where(where_clause)
.order_by(EventModel.start_time.asc(), EventModel.id.asc())
.limit(10)
.with_cte(cte)
After reading the docs twenty+ times, I can't figure out what isn't right about this. It looks like the samples... but the query will fail, because "relation "test" does not exist". I've played with "columns" being explicitly defined, but then that throws an error that "rn is ambiguous".
I'm stuck and not sure how I can get Peewee CTE to work.

How can you pass the same argument twice in a python sqlite3 nested query?

I am trying to pass data into a nested sqlite3 query in python and I get the following error
Incorrect number of bindings supplied. The current statement uses 2, and there are 1 supplied.
x = uid
sql_query1 = """SELECT title FROM movies WHERE addedBy != ? AND mid NOT IN (SELECT mid FROM ratings WHERE uid = ?);"""
data = (uid, x)
cursor.execute(sql_query1, [data])
movies = cursor.fetchall()
I'm guessing the problem might be that x = uid, I have also tried data = (uid, uid) and cursor.execute(sql_query1, [uid]).
Parameters can be explicitly numbered, and the same value used for all instances of a given number:
sql_query1 = """
SELECT title
FROM movies
WHERE addedBy != ?1 AND mid NOT IN (SELECT mid FROM ratings WHERE uid = ?1);"""
cursor.execute(sql_query1, (uid,))
You need to supply as many parameters as you have question marks.
cursor.execute("""
SELECT title
FROM movies
WHERE addedBy != ?
AND mid NOT IN (SELECT mid FROM ratings WHERE uid = ?);
""", [uid, uid])
movies = cursor.fetchall()

SQLALCHEMY: Problem with subquery select, How do i a exact subquery with outerjoin?

I'd like to get a select by a sub-query but, I don't know how I will do that. I searched for every world of internet but not found what i want.
The select is:
SELECT order_status.*
FROM `order`
LEFT OUTER JOIN
(
SELECT *
FROM (
SELECT *
FROM order_status
ORDER BY created_date DESC LIMIT 1) s
WHERE status IN ('NEW', 'FINISH','SENDED','PROCESSING')
) AS order_status ON order.id = order_status.order_id;
my code:
subqy = self.session.query(OrderStatus).order_by(OrderStatus.created_date.desc()).limit(1).subquery()
query = self.session.query(Order).outerjoin(subqy)
return query.filter(and_(in_(conditions))).all()
I'd change the query a little bit to remove one subquery:
SELECT order_status.*
FROM `order`
LEFT OUTER JOIN
(
SELECT *
FROM order_status
ORDER BY created_date DESC
LIMIT 1
) AS order_status ON order.id = order_status.order_id
AND order_status.status IN ('NEW', 'FINISH','SENDED','PROCESSING')
Then the code becomes
subquery = self.session\
.query(OrderStatus)\
.order_by(OrderStatus.created_date.desc())\
.limit(1)\
.subquery()
query = self.session.query(Order)\
.outerjoin(subquery,
(subquery.c.order_id == Order.id)
& subquery_a.c.status.in_(('NEW', 'FINISH','SENDED','PROCESSING')))
return query.all()
I think the thing you missed is that for subqueries, you need to access the columns through table.c.column, instead of Table.column, as you're used to.

Two SELECT Statements NESTED

I have been trying to execute the following query, but it doesn't give me any output.
self.db.execute("SELECT * FROM patients WHERE patients.doctorid = (SELECT id FROM doctors WHERE username = '%s' % (usr)), callback=self.add_response)
I tried to execute the same query by hardcoding the values and it gives me the correct output.
select * from patients where patients.doctorid = (select id from doctors where username = 'admin');
Can someone tell whats the error?
Try to execute it like this:
self.db.execute("SELECT * FROM patients WHERE patients.doctorid = (SELECT id FROM doctors WHERE username = '%s')" % (usr), callback=self.add_response)
I closed the SQL query with " and fixed the parentheses.
You can also try as shown here:
self.db.execute("SELECT * FROM patients WHERE patients.doctorid = (SELECT id FROM doctors WHERE username = '%s';", (usr), callback=self.add_response)

Recursive CTE Query

I am having an issue constructing the SQLAlchemy code required to produce the following raw SQL query.
WITH RECURSIVE recruiters AS (
SELECT
recruiter.id
FROM
recruiter
JOIN
recruiter_member ON recruiter.id = recruiter_member.recruiter_id
WHERE
recruiter_member.user_id = 'f12c617a-415c-4f8c-add0-81a597545be8'
UNION ALL
SELECT
children.id
FROM
recrutiers AS parents,
recruiter AS children
WHERE
children.recruiter_id = parents.id
)
SELECT
*
FROM
recruiters
The models here are Recruiter and RecruiterMember. I just can't seem to get the UNION right.
Without more details, this was the best I could come up with:
from sqlalchemy import orm
parent = orm.aliased(Recruiter)
child = orm.aliased(Recruiter)
top_q = (
orm.query.Query([Recruiter.id.label('id')])
.join(RecruiterMember, Recruiter.id == RecruiterMember.recruiter_id)
.filter(RecruiterMember.user_id == 'f12c617a-415c-4f8c-add0-81a597545be8')
.cte(recursive=True))
bottom_q = (
orm.query.Query([child.id.label('id')])
.join(parent, parent.id == child.recruiter_id))
final_query = top_q.union_all(bottom_q)
orm.query.Query([final_query.c.id]).with_session(session).all()

Categories

Resources