Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

281
Views
SQLAlchemy query with conditional filters and results

I'm building a fastAPI app and I have a complicated query that I'm trying to avoid doing as multiple individual queries where I concat the results. I have the following tables that all have foreign keys:

CHANGE_LOG: change_id | original (FK ROSTER.shift_id) | new (FK ROSTER.shift_id) | change_type (FK CONFIG_CHANGE_TYPES)

ROSTER: shift_id | shift_type (FK CONFIG_SHIFT_TYPES) | shift_start | shift_end | user_id (FK USERS)

CONFIG_CHANGE_TYPES: change_type_id | change_type_name

CONFIG_SHIFT_TYPES: shift_type_id | shift_type_name

USERS: user_id | user_name

FK= Foreign Key

I need to return the following information: user_name, change_type_name, and shift_start shift_end and shift_type_name for those whose shift_id matches the original or new in the CHANGE_LOG row.

The catch is that the CHANGE_LOG table might have both original and new, only an original but no new, or only a new but no original. But as the user can select a few options from drop down boxes before submitting the request, I also need to be able to include a filter to single out:

  1. just one user, or all users
  2. any change_type, or a group of change_types

The issue is that I can't find a way to get the user_name guaranteed for each row without inspecting it afterwards because I don't know if the new or original exist or are set to null.

Is there a way in SQLalchemy to have an optional filter in the query where I can say if the original exists use that to get the user_id, but if not then use the new to get the user_id. Also, if i have a query that definitely finds those with original and new shifts, it will never find those with only one of them as the criteria will never match.

I've also read this and similar ones, and while they'll resolve the issue of conditionally setting some of the filters, it doesn't get around the issue of part nulls returning nothing at all, rather than half the data. This one seems to solve that problem, but I have no idea how to implement it.

I know it's complicated, so let me know if I've done a poor job of explaining the question.

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Sorted. The solution was to use the outerjoin option. I'm sure the syntax can be more elegant than my solution if I properly engage in adding relationships when defining each class, but what I end up with is explicit and I think it makes it easier to read... at least for me.

Since I'm using a few tables more than once in the same query for different information, it was important to alias those, otherwise I ended up with a conflict (which 'user_id' did you want - it's not clear). For those playing at home, here's my general solution:

new=aliased(ROSTER)
original=aliased(ROSTER)
o_name=aliased(CONFIG_SHIFT_TYPES)
n_name=aliased(CONFIG_SHIFT_TYPES)

pd.read_sql(
  db.query(
    CHANGE_LOG.change_id,
    CHANGE_LOG.created,
    CONFIG_CHANGE_TYPES.change_name,
    o_name.shift_name.label('original_type'),
    n_name.shift_name.label('new_type'),
    OPERATORS.operator_name
  )
  .outerjoin(original, original.shift_id==CHANGE_LOG.original_shift)
  .outerjoin(new, new.shift_id==CHANGE_LOG.new_shift)
  .outerjoin (CONFIG_CHANGE_TYPES,CONFIG_CHANGE_TYPES.change_id==CHANGE_LOG.change_type)
  .outerjoin(CONFIG_SHIFT_TYPES, CONFIG_SHIFT_TYPES.shift_id==new.roster_shift_id)
  .outerjoin(o_name, o_name.shift_id==original.roster_shift_id)
  .outerjoin(n_name, n_name.shift_id==new.roster_shift_id)
  .outerjoin(USERS, or_(USERS.operator_id==original.user_id, USERS.user_id==new.user_id)
  ).statement, engine)
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!