Undefer all tables in SQLAlchemy? - python

Is there direct syntax to undefer all columns in a query object?
I know there is a way of undefering groups, but I have a query touching many tables with many groups deferred that I'd like to undefer. It's getting a bit verbose.
I know you can undefer all columns in a single Table, but what about doing it for every Table:
# undefer all columns specific to a single class using Load + *
session.query(MyClass, MyOtherClass).options(
Load(MyClass).undefer("*"))
http://docs.sqlalchemy.org/en/latest/orm/loading_columns.html#sqlalchemy.orm.undefer

Related

Union of tables with common column name but different column type

I am a beginner in flask-sqlalchemy and application development.
I am really stuck at a situation where I need to do union of 3 tables but one of the columns of the of these tables have different column type but same column name. I use postgres DB for testing my python code which uses sqlalchemy.
I try casting the column to string to match the first query column i.e. TableCategorical.value, but my issue is that I need to remove the casting after union to get the original column type for the rest of the code.
How do I do that?
CODE:
query_1 = select(TableCategorical.name_id, TableCategorical.measurement,
TableCategorical.key, TableCategorical.value)
query_2 = select(TableNumerical.name_id, TableNumerical.measurement,
TableNumerical.key, cast(TableNumerical.value, String))
query_3 = select(TableDate.name_id, TableDate.measurement,
TableDate.key, cast(TableDate.value, String))
query_union = union(query_1, query_2, query_3)
I have done my part of searching online to get a solution but I am not able to.

How to implement a specific SQL statement as a SQLAlchemy ORM query

I was following a tutorial to make my first Flask API (https://medium.com/#dushan14/create-a-web-application-with-python-flask-postgresql-and-deploy-on-heroku-243d548335cc) I did it but now I want to do queries more custom with SQLAlchemy and PostgreSQL. My question is how I could do something like this:
query = text("""SELECT enc.*, persona."Persona_Nombre", persona."Persona_Apellido", metodo."MetEnt_Nombre", metodo_e."MetPag_Descripcion"
FROM "Ventas"."Enc_Ventas" AS enc
INNER JOIN "General"."Persona" AS persona ON enc."PersonaId" = persona."PersonaId"
INNER JOIN "Ventas"."Metodo_Entrega" AS metodo ON enc."MetodoEntregaId" = metodo."MetodoEntregaId"
INNER JOIN "General"."Metodo_Pago" AS metodo_e ON enc."MetodoPagoId" = metodo_e."MetodoPagoId"
INNER JOIN "General"."Estatus" AS estado ON enc. """)
but with SQLAlchemy in order to use the models that I created previously. Thanks in advance for any answer!!
Edit:
The columns that I wish to see at the final result are: enc.*, persona."Persona_Nombre", persona."Persona_Apellido", metodo."MetEnt_Nombre", metodo_e."MetPag_Descripcion"
I really wish I could share more info but sadly I can't at the moment.
Doing this from the ORM layer, you would reference model names (I match the names of your query above, but I'm sure some of the model/table names are off - now adjusted slightly).
Now revised to include the specific columns you only want to see (note that I ignore your SQL aliases, ORM layer handles the actual query construction):
selection = session.query(Enc_Ventas, Persona.Persona_Nombre, Persona.Persona_Apellido, Metodo_Entrega.MetEnt_Nombre, Metodo_Pago.MetPag_Descripcion).\
join(Persona, Enc_Ventas.PersonaId == Persona.PersonaId).
join(Metodo_Entrega, Enc_Ventas.MetodoEntregaId == Metodo_Entrega.MetodoEntregaId).\
join(Metodo_Pago, Enc_Ventas.MetodoPagoId == Metodo_Pago.MetodoPagoId).\
join(Estatus).all()
Referencing the selection collection would be by iteration through the rows of tuples. A more robust and stable solution would be to transform each output row into a dict.
Otherwise, by including whole models, the collection of rows returned can be individually accessed by referencing as dot notation the model names in the query().
If you need further access to the columns in the related tables, use the ORM technique of .options(joinedload(myTable)), which in a single database query will bring in those additional columns, using the relationship name, also as dot notation.
You also need to define sqlalchemy relationships within your models for this to work, as well as defining the underlying SQL foreign keys.
Much more detail and/or a more specific question is needed to help further, imo.

How do you compare two tables with the same columns but in a different order (SQL or python)?

I am trying to find out how to see if two table are the same in sql. The tables should be the exact same but the order of the columns is slightly different. My initial though is to subtract the two tables from eachother and verify that the result is 0 records but I do not think this will work because of the difference in the order of columns. Any suggestions? Your help is much appreciated,
Thank you,
John
If what you want is to compare tables you can try the following; minus and except depends on the SQL used by yout Data Base Management System.
select * from tableA
minus
select * from tableB
If no rows are return by query then data is the same for both tables,now this will work if both have same amount of rows.
When comparing different entries in two different columns size you will need to use
LEFT JOIN
There is some source material you can use for reference:
Union! SQL Server
Compare two tables with different entries and column
Might not be the answer you are looking for, but you could create a view and select the columns in the matching order from there. Then the comparison should be easier.
You can perform a full outer join on each field, then compare the length of the result to the length both original tables.
SELECT * from
Table_A FULL OUTER JOIN
Table_B on
A.Field_X = B.Field_X
A.Field_Y = B.Field_Y
If the view returns the same number of results as the length of both original tables, then the two tables are the same for those fields.

Querying with joins in sql alchemy and avoiding select all

I would like to know wether there is a way to combine joining two tables, and retrieving the two entities only with their relevant columns.
I want to avoid doing a thing such select * after joining two tables and getting only column id from Table A and column address from table B.
Working with python2.7
I heard of sqlalchemy feature called with_entities, but not sure how can it be mixed with this kind of join, lets work on this example from sqlalchemy tutorial:
u, a = session.query(User, Address).\
filter(User.id==Address.user_id).\
filter(Address.email_address=='jack#google.com').\
first():
Check out Query.join()
id, address = session.query(A.id, B.address).\
join(B, B.user_id == A.id).\
filter(A.email_address=='jack#google.com').\
first()
This can be done using a join or outerjoin depending on the use case, joins can be implicit or explicit. The .join second argument is the explicit join statement.

What's the most efficient way to get this information from the database?

Related to this question:
Wildcards in column name for MySQL
Basically, there are going to be a variable number of columns with the name "word" in them.
What I want to know is, would it be faster to do a separate database call for each row (via getting the column information from the information schema), with a generated Python query per row, or would it be faster to simply SELECT *, and only use the columns I needed? Is it possible to say SELECT * NOT XYZ? As far as I can tell, no, there is no way to specifically exclude columns.
There aren't going to be many different rows at first - only three. But there's the potential for infinite rows in this. It's basically dependent on how many different types of search queries we want to put on our website. Our whole scalability is based around expanding the number of rows.
If all you are doing is limiting the number of columns returned there is no need to do a dynamic query. The hard work for the database is in selecting the rows matching your WHERE clause; it makes little difference to send you 5 columns out of 10, or all 10.
Just use a "SELECT * FROM ..." and use Python to pick out the columns from the result set. You'll use just one query to the database, so MySQL only has to work once, then filter out your columns:
cursor.execute('SELECT * FROM ...')
cols = [i for i, col in enumerate(cursor.description) if col[0].startswith('word')]
for row in cursor:
columns = [row[c] for c in cols]
You may have to use for row in cursor.fetchall() instead depending on your MySQL python module.

Categories