On Oct 9, 2012, at 9:54 AM, Benjamin Gonzalez wrote: > > Hi, > > I've been using SQLAlchemy for the last couple of weeks. I'll definitely > call myself a beginner so I apologize if I'm missing something obvious with > this question :)
> I'm working with a database where there is data split across tables with the > exact same structure, so there are cases where I need to query more than one > table and filter by the same criteria. this sounds like you're describing horizontal partitioning. such as if a particular row of data could equally well be in one table or the other, and its only some kind of sharding scheme that determines which table. > Looking around in the documentation I read about Concrete Table Inheritance > and thought that could help me in this case. yeah concrete inheritance is not really intended for this case, though I can see what you're going for. > And perform a query such as: > > session.query(Employee).filter(Employee.name=='test') > > It will apply the name filter after the union is done: > > SELECT pjoin.employee_id AS pjoin_employee_id, pjoin.name AS pjoin_name, > pjoin.type AS pjoin_type, pjoin.manager_data AS pjoin_manager_data, > pjoin.engineer_info AS pjoin_engineer_info > FROM (SELECT employees.employee_id AS employee_id, employees.name AS name, > CAST(NULL AS VARCHAR(50)) AS manager_data, CAST(NULL AS VARCHAR(50)) AS > engineer_info, 'employee' AS type > FROM employees UNION ALL SELECT managers.employee_id AS employee_id, > managers.name AS name, managers.manager_data AS manager_data, CAST(NULL AS > VARCHAR(50)) AS engineer_info, 'manager' AS type > FROM managers UNION ALL SELECT engineers.employee_id AS employee_id, > engineers.name AS name, CAST(NULL AS VARCHAR(50)) AS manager_data, > engineers.engineer_info AS engineer_info, 'engineer' AS type > FROM engineers) AS pjoin > WHERE pjoin.name = :name_1 > > Is there a way to ask SQLAlchemy to apply the filter to each table in the > inner queries? They all have a name column, and in the case of a large > dataset it's helpful because it avoids loading all the rows for each table > first and then applying the WHERE clause. oh OK so you're taking advantage of the UNION generated by polymorphic_union to try filtering across all those tables. this is a funny case because we do have an extension that serves as an example for "horizontal partitioning", which is in sqlalchemy.ext.horizontal_shard, but that example is architected around the idea that you're talking to multiple database backends, each of which has just one table in it. So it doesn't do the UNION thing which of course is preferable if it is possible. One example that might be worth peeking at is how this mapping scheme can be set up without necessarily using Concrete inheritance, though really it's probably easier that you are just using the concrete system, that example is at: http://www.sqlalchemy.org/trac/wiki/UsageRecipes/EntityName . It has a "classical" version and a "declarative" version, though the declarative is a bit awkward. Stick with the concrete if that's easier. As far as the query, to come up with an ad-hoc, filtered UNION would have to be invented. I'd start by working it out manually using Query, then perhaps trying to genericize it, either that you have a simple function that comes up with a Query with unions, or if you really need to do this fluently, as a Query subclass. Here's sort of the idea of that: def query_all_shards(session, criterion): q = None for subclass in MyConcreteBase.__subclasses__(): if q is None: q = session.query(subclass).filter(criterion) else: union_q = session.query(subclass).filter(criterion) q = q.union_all(union_q) return q I haven't tested this, but something like that. Then if you wanted to bake this into Query, you could build a Query subclass that does this, giving it a method like "union_on_shards()" that would trigger a "union" operation similar to the above. There's a Query subclass example in the sqlalchemy/ext/horizontal_shard.py module, and also in some of the wiki examples such as http://www.sqlalchemy.org/trac/wiki/UsageRecipes/PreFilteredQuery . Overall I'd stay away from polymorphic_union as a mapper-level default since it generates huge beasts of queries, which you often won't want. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalchemy@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.