I have the following tables defined (very simplified version):
class Orders(db.Model):
id = db.Column(db.Integer, primary_key=True)
order_id = db.Column(db.Integer,nullable=False)
date_created = db.Column(db.DateTime, nullable=False)
class ProductOrders(db.Model):
id = db.Column(db.Integer, primary_key=True)
order_id = db.Column(db.Integer, nullable=False)
product_id = db.Column(db.Integer, nullable=False)
base_price = db.Column(db.Float, nullable=False)
I am using BigCommerce API and have multiple order_ids in both tables. The order_id is not unique globally but is unique per store. I am trying to work out how to link the two tables. I do have a Store table (shown below) that holds the store.id for each store, but I just cannot work out how to join the Orders and ProductOrders tables together so I can access both tables data where the store.id is the same. I just want to query, for example, a set of Orders.order_id or Orders.date_created and get ProductOrders.base_price as well.
class Store(db.Model):
id = db.Column(db.Integer, primary_key=True)
Any ideas?
Assuming id in both queries is the store_id and order_id is unique per store, you will have to apply join with AND statement.
For example: (in SQL)
Orders join ProductOrders on Orders.id = ProductOrders.id and Orders.order_id = ProductOrders.order_id
Answer is based on what I have understood from your question, sorry if that's not your required answer.
Edit:
In sqlalchemy it would be something like below:
from sqlalchemy import and_
session.query(Orders, ProductOrders).filter(and_(Orders.id == ProductOrders.id, Orders.order_id == ProductOrders.order_id)).all()
References:
https://www.tutorialspoint.com/sqlalchemy/sqlalchemy_orm_working_with_joins.htm
Using OR in SQLAlchemy
Related
I am using the python project dedupe to find duplicate organization names in my data. Many of the examples are focused on how to process the data and not how the results are implemented. Are there any best practices for taking the results, putting it into your database, and querying to group records that are duplicates?
My thoughts so far are to structure the two tables like this (using sqlalchemy), but I feel like something is off about it:
class Organization(Base):
__tablename__ = 'organization'
id = Column(Integer, primary_key=True)
name = Column(String)
cluster_id = Column(Integer, ForeignKey('duplicate_organization.cluster_id'))
class DuplicateOrganzation(Base):
__tablename__ = 'duplicate_organization'
id = Column(Integer, primary_key=True)
cluster_id = Column(Integer)
name = Column(String)
organizations = relationship("Organization")
i have a the following model:
class Tables(db.Model): # fixme: rename the table name to table.
__tablename__ = "tables"
id = db.Column(db.Integer, primary_key=True)
store_id = db.Column(db.Integer)
name = db.Column(db.String(64))
active = db.Column(db.Integer, default=0)
orders = db.relationship("Order", backref='table', lazy='dynamic')
So far i have this.
tables = Tables.query.filter_by(store_id=1).all()
free_tables = []
for table in tables:
if len(table.orders.all()) == 0:
free_tables.append(table.id)
what i want are the ids of the tables that have no orders bound to them. Is there a way to write this in a single line? thank you.
Try this:
from sqlalchemy import not_
tables = Tables.query.filter_by(store_id=1)\
.filter(not_(Tables.orders.any())).all()
Suppose I have several tables and want to perform join query:
schedule_calendars = ScheduleCalendar.query\
.join(Schedule)\
.join(ClinicBranchHasDoctor)\
.filter_by(clinic_branch_id=clinic_id, doctor_has_specialty_id=doctor_speciality_id).all()
The thing is here is that my result will only contain attributes of ScheduleCalendar class. How do I query such that my result will contain attributes of all joined tables.
Schedule:
id = Column(db.Integer, primary_key=True)
added_date = Column(db.DateTime(timezone=True), default=get_current_time, nullable=False)
start_date = Column(db.Date, nullable=False)
name = Column(db.String(128), nullable=False)
is_valid = Column(db.Boolean, default=IS_VALID, nullable=False)
slot_size = Column(db.Integer, default=30)
ScheduleCalendar:
schedule_id = Column(db.Integer, db.ForeignKey("schedules.id"), nullable=False)
ClientBranchHasDoctor:
schedule_id = Column(db.Integer, db.ForeignKey("schedules.id"), nullable=False)
I skipped some attributes here. I think the most important is that my tables have appropriate constraints, otherwise join will fail.
You need to add a back reference to your classes.
For example, in your ScheduleCalendar class, add:
schedule_id = Column(db.Integer, db.ForeignKey("schedules.id"), nullable=False)
schedule = db.relationship("Schedule", back_populates="calendar", lazy="dynamic")
And in your Schedule class add:
calendar = db.relationship("ScheduleCalendar", back_populates="schedule")
Now you can access Schedule objects from ScheduleCalendar.
In your example, you would access it like this:
schedule_calendars = ScheduleCalendar.query\
.join(Schedule)\
.join(ClinicBranchHasDoctor)\
.filter_by(clinic_branch_id=clinic_id, doctor_has_specialty_id=doctor_speciality_id).all()
schedule_calendars[0].schedule
I tried many answers but was not able to join tables to get its column data at the same time. After creating back reference as suggested by #AArias you can use this code to get your table's data.
results = db.session.query(Schedule, ScheduleCalendar, ClientBranchHasDoctor). \
select_from(Schedule).join(ScheduleCalendar).join(ClientBranchHasDoctor).all()
for schedule,scheduleCalendar,hasDoctor in results:
print(schedule.name, scheduleCalendar.schedule_id , hasDoctor.schedule_id)
This way you can access all data of 3 tables simultaneously.
I have 2 tables defined:
class TCableSet(Base):
__tablename__ = 'tCableSet'
ixCableSet = Column(Integer, primary_key=True)
decCableSetOne = Column(Numeric(8, 2))
decCableSetTwo = Column(Numeric(8, 2))
decCableSetThree = Column(Numeric(8, 2))
class TStepVoltage(Base):
__tablename__ = 'tStepVoltage'
ixStepVoltage = Column(Integer, primary_key=True)
ixSubReport = Column(Integer, ForeignKey('tSubReport.ixSubReport'), nullable=False)
iVoltage = Column(Integer)
ixPhaseA = Column(Integer, ForeignKey('tCableSet.ixCableSet'), nullable=False)
ixPhaseB = Column(Integer, ForeignKey('tCableSet.ixCableSet'), nullable=False)
ixPhaseC = Column(Integer, ForeignKey('tCableSet.ixCableSet'), nullable=False)
sub_report = relationship('TSubReport',
backref=backref('step_voltage'))
I understand why I am getting this error but can't figure out a proper way (yet).
When the table gets saved, I store the values in the tCableSet table and then use the id as a foreign key in my tStepVoltage table. The problem I have is when I go to retrieve the data, I want to be able to get the values(tCableSet row) along with the rest of my tStepVoltage table via a relationship, however I'm not sure how to go about this since I don't have a field in my tCableSet that can directly be linked via relationship to my tStepVoltage. I basically just needed the tCableSet for normalization
Since you have more than one foreign key that points to the same table, you have to tell SQLAlchemy which foreign key to use.
For example:
sub_report_a = relationship('TSubReport',
backref=backref('step_voltage'),
foreign_keys=[ixPhaseA])
I'm new with sqlalchemy and I want to do this as simply as possible, yet correctly. I want to track domain use across multiple companies on a monthly basis, so I set up the following tables:
class Company(Base):
__tablename__ = 'company'
id = Column(Integer, primary_key = True)
name = Column('name', String)
class Domains(Base):
__tablename__ = 'domains'
id = Column(Integer, primary_key=True)
name = Column('name', String, unique=True)
class MonthlyUsage(Base):
'''
Track domain usage across all
companies on a monthly basis.
'''
__tablename__ = 'monthlyusage'
month = Column(DateTime)
company_id = Column(Integer, ForeignKey('company.id'))
domain_id = Column(Integer, ForeignKey('domains.id'))
# <...other columns snipped out...>
company = relationship('Company', backref='company_assoc')
domain = relationship('Domains', backref='domain_assoc')
This works fine, until I add usage details for the second month. Then I get duplicate key value errors:
*sqlalchemy.exc.IntegrityError: (IntegrityError) duplicate key value violates unique constraint "monthlyusage_pkey"*
Does this mean I have to split out the "monthlyusage" into a third table? That seems unnecessarily complicated, since all that needs to be unique is the month, company_id, and domain_id fields.
Any suggestions for my layout here, to keep it as simple as possible, yet still correct?
TIA!
Ok, I needed to add a primary key column to MonthlyUsage. The code below now works...
class MonthlyUsage(Base):
'''
Track domain usage across all
companies on a monthly basis.
'''
__tablename__ = 'monthlyusage'
month = Column(DateTime)
month_id = Column(Integer, primary_key=True)
company_id = Column(Integer, ForeignKey('company.id'), primary_key=True)
domain_id = Column(Integer, ForeignKey('domains.id'), primary_key=True)
# <...other columns snipped out...>
company = relationship('Company', backref='company_assoc')
domain = relationship('Domains', backref='domain_assoc')