Hi all,
Since SA was proving to be difficult to get working, and I was
spending way more time just trying to get it working than I was
actually running queries and outputting the results, I thought I'd
give Pyodbc a shot. Within a couple days, the query was working
perfectly. I'll post it below, as I'd be curious how this could be
made easier using SA. I don't know that I'll use SA for this project
since it's working so well in Pyodbc, but I'm curious all the same.
So, no hurry on this, it's only for my own interest. Anyway, the query
I finally came up with is below. It returns multiple rows for items
that have attributes, but other than that it works great. A for loop
with a check on the current ID takes care of making multiple rows for
the same item into a single row (recall this is all going to a
spreadsheet).


itemsQuery = """
 select items.itm_id as itemID, items.itm_proddesc as itemTitle,
items.itm_num as itemNumber, items.itm_listprice1 as msrp,
items.itm_dftuom as itemUnitOfMeasure, items.itm_manufitem as
itemManufacturer, items.itm_vendornum as itemVendorNumber,
  items.itm_weight as itemWeight, items.itm_width as itemWidth,
items.itm_length as itemLength, items.itm_height as itemHeight,
  attachments.description as description,
  imagePaths.imagePath1 as imagePath1, imagePaths.imagePath2 as
imagePath2, imagePaths.imagePath3 as imagePath3,
  attributes.attributeName as attributeName, attributes.attributeValue
as attributeValue,
  vendor.vendorName as vendorName
  from (
   select itm_id, itm_proddesc, itm_num, itm_vendornum,
itm_listprice1, itm_length, itm_width, itm_height, itm_weight,
itm_dftuom, itm_manufitem
   from item
   where itm_webflag <> 'Y' and itm_suspflag <> 'Y'
  ) items
  left outer join (
   select distinct attr_desc as attributeName, attr_value as
attributeValue, itm_id
   from attributevalueassign
   join attribute
   on attribute.attr_id = attributevalueassign.attr_id
   join attributevalue
   on attributevalue.attr_value_id = attributevalueassign.attr_value_id
   where attributevalueassign.itm_id = itm_id
  ) attributes
   on attributes.itm_id = items.itm_id
  left outer join (
   select PVUS15 as vendorName, PVVNNO as vendorNumber, itm_id
   from VENDR
   join item on item.itm_id = itm_id
  ) vendor
on vendor.vendorNumber = items.itm_vendornum and vendor.itm_id = items.itm_id
  left outer join (
 select attach_text.att_text as description, itm_id
  from assignment
   join attachment on attachment.att_id = assignment.att_id
   join attach_text on attach_text.att_id = assignment.att_id
   where assignment.itm_id = itm_id
  ) attachments
  on attachments.itm_id = items.itm_id
  left outer join (
   select attachment.att_path as imagePath1, attachment.att_path2 as
imagePath2, attachment.att_path3 as imagePath3, itm_id
   from assignment
   join attachment on attachment.att_id = assignment.att_id
  ) imagePaths
  on imagePaths.itm_id = items.itm_id
"""


On 3/21/16, Simon King <si...@simonking.org.uk> wrote:
> Can you extract your code into a single standalone script that demonstrates
> the problem? This should be possible even with automap; the script can
> start by creating just the tables that are involved in this problem
> (ideally in an in-memory sqlite db), then use automap to map classes to
> those tables.
>
> Simon
>
> On Mon, Mar 21, 2016 at 3:12 PM, Alex Hall <ah...@autodist.com> wrote:
>
>> Wow, thanks guys, especially for the sample code! I'm trying to use
>> the example (and fully understand it at the same time) but am running
>> into an error. This is the same error that made me look for a way
>> other than this last week.
>>
>> sqlalchemy.exc.InvalidRequestError: when initializing mapper
>> Mapper|assignmentTable|assignment, expression 'item' failed to to
>> locate an item (name 'item' is not defined). If this is a class name,
>> consider adding this relationship() to the
>> <class.__main__.assignmentTable> class after both dependent classes
>> have been defined.
>>
>> This all starts from the line where my query begins:
>>
>> items = session.query(itemTable)\
>>
>> Again, I'm using automap. I put the class definitions in the same
>> place I put my vendor table definition last week, where it worked
>> perfectly. That's just after I set
>> base = automap_base()
>> but before I reflect anything. I can paste the full code if you want,
>> but it's pretty long.
>>
>> On 3/17/16, Mike Bayer <clas...@zzzcomputing.com> wrote:
>> >
>> >
>> > On 03/17/2016 03:11 PM, Alex Hall wrote:
>> >> Hello all,
>> >> It seems like I can't go a day without running into some kind of wall.
>> >> This one is a conceptual one regarding foreign keys. I have to somehow
>> >> get the same FK column in table A pointing to IDs in tables B and C.
>> >
>> > So a real foreign key constraint is not capable of this.  Repurposing a
>> > single column to occasionally point to one table or another is a famous
>> > anti-pattern I've spoke of much (warning, this is *extremely* old, but
>> > the general idea still holds):
>> >
>> >
>> http://techspot.zzzeek.org/2007/05/29/polymorphic-associations-with-sqlalchemy/
>> >
>> >
>> > I have an updated version of all the various "polymoprhic association"
>> > examples in SQLAlchemy itself at
>> >
>> http://docs.sqlalchemy.org/en/rel_1_0/orm/examples.html#module-examples.generic_associations
>> .
>> >
>> >   This includes the "single column pointing to multiple tables" hack,
>> > as
>> > well as three other versions of the same business object geometry which
>> > preserve relational integrity within the schema design.
>> >
>> >>
>> >> At one person's suggestion, I'm making classes for my tables, even
>> >> though I'm using automap. This is to let me stop doing a ton of joins,
>> >> making querying much easier... I hope! I'm defining all the foreign
>> >> keys between my tables manually. For instance:
>> >>
>> >> class item(base):
>> >>   __tablename__ = "item"
>> >>   itm_id = Column(Integer, primary_key=True)
>> >>   vendornum = Column(String, ForeignKey(VENDR.PVVNNO))
>> >>
>> >> class vendorTable(base):
>> >>   __tablename__ = "VENDR"
>> >>   PVVNNO = Column(String, primary_key=True)
>> >>
>> >> If I've understood correctly, I'll now be able to say
>> >> item.vendornum.vendor_full_name
>> >> to get the vendor's full name for any item.
>> >>
>> >> Here's the problem. Items have attachments, and attached text,
>> >> respectively held in attach and attach_text tables. Binding them to
>> >> items is a table called assignment. Assignment is pretty
>> >> straightforward, with an itm_id and an attachment id (att_id). The
>> >> trouble is that this att_id occurs in both attach and attach_text. I
>> >> can make att_id a foreign key to one table or the other, but I'm not
>> >> sure how to make it go to both tables.
>> >
>> > the "generic_fk" example illustrates a pattern for working with this.
>> >
>> > Getting this all to work with automap is another layer of complexity,
>> > you certainly want all of this part of it laid out before you reflect
>> > the rest of the database columns.
>> >
>> >
>> >>
>> >> class assignmentTable(base):
>> >>   __tablename__ = "assignment"
>> >>   itm_id = Column(Integer, ForeignKey(item.itm_id))
>> >>   #the following column has to point to attach_text.att_id AS WELL
>> >>    att_id = Column(Integer, ForeignKey(attachment.att_id))
>> >>   seq_num = Column(Integer)
>> >>   asn_primary = Column(Integer, nullable=True)
>> >>
>> >> class attachmentTable(base):
>> >>   __tablename__ = "attachment"
>> >>   att_id = Column(Integer, primary_key=True)
>> >>
>> >> class attachmentTextTable(base):
>> >>   __tablename__ = "attach_text"
>> >>   att_id = Column(Integer, primary_key=True)
>> >>
>> >
>> > --
>> > You received this message because you are subscribed to the Google
>> > Groups
>> > "sqlalchemy" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
>> > an
>> > email to sqlalchemy+unsubscr...@googlegroups.com.
>> > To post to this group, send email to sqlalchemy@googlegroups.com.
>> > Visit this group at https://groups.google.com/group/sqlalchemy.
>> > For more options, visit https://groups.google.com/d/optout.
>> >
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "sqlalchemy" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to sqlalchemy+unsubscr...@googlegroups.com.
>> To post to this group, send email to sqlalchemy@googlegroups.com.
>> Visit this group at https://groups.google.com/group/sqlalchemy.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
> --
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to sqlalchemy+unsubscr...@googlegroups.com.
> To post to this group, send email to sqlalchemy@googlegroups.com.
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to