Get distinct values from sqlAlchemy object - sqlalchemy

I have two models: Product and MBiopoint.
They are related through a many to many table named t_Dataset_Data. In Product table there is the attribute 'data' declared like this:
data = relationship(u'MBiopoint', secondary=t_Dataset_Data)
So when I query the Product table for a specific product like this:
prod = session.query(Product).filter_by(product_id=69).first()
i can now have access to all MBiopoint records that are associated with my product in the many to many table, through this code for example (to access the value of datastatus column of MBiopoint):
for pd in prod.data:
print pd.datastatus
What I need now is to get the distinct values of 'datastatus' column of all data records associated with my product without using a for loop, something like this: d = prod.data.datastatus.distinct()
Do you have any idea?
Otherwise, I can I get the distinct values using the for loop?

Using the freenode Web IRC webchat, the user with the nickname 'agronholm' gave a solution for my problem.
What he suggested was:
set(pd.datastatus for pd in prod.data)
or in a modern way:
{pd.datastatus for pd in prod.data}
That worked for me.

Related

Pulling data from two tables (for a 'related products' query) in MySQL

I'm trying to pull data from two tables for a 'related products' widget.
I've tried all the JOINS and UNIONS I can and still get nothing.
The first table (productdocs) stores documents. The second (prodrelated) shows when a product is related to a document:
productdocs
pdid (unique ID for the document)
pdname (name of the uploaded document)
prodrelated
prprodid (the ID for the PRODUCT)
pritemid (the ID for the document)
I am trying to output the productdocs.pdname for any documents that match up with the product's id. In otherwords, show the pdname when:
WHERE productdocs.pdid = prodrelated.pritemid
I would post my SQL code, but none of it has worked, so I think it would be pointless. I hope I explained this correctly given my frazzled brain - Any help greatly appreciated.
You can use a simple INNER JOIN for this, e.g.:
SELECT pd.pdid, pd.pdname
FROM productdocs pd JOIN prodrelated pr ON pd.pdid = pr.pritemid
WHERE pd.prprodid = <any_id>;
If you don't want to filter out any records, you can get rid of WHERE clause and it will output all the records.
Here's MySQL's documentation for JOIN.
Wow you guys are fast - thank you so much.
Darshan - thank you above all, I was able to make a few mods to what you wrote and it worked great. I tried to +1 your answer but maybe I don't have enough 'reputation'? Here is what I got working, thanks to you:
SELECT pd.pdid, pd.pdname
FROM productdocs pd
JOIN prodrelated pr
ON pd.pdid = pr.pritemid
WHERE pr.prprodid = '#url.prodid#'
In the future I will try to post some code example, but on this one I honestly tried at least 7 different queries so I had no idea which to post!

How to limit results in reverse relation in Django

I have two tables, one called Company and the other called User, each user is related to one company using ForeignKey. So I can use reverse relation in Django to get all users for specific company (e.g. company.users)
In my case, I'm building ListAPIView which return multiple companies, and I'd like to return latest created user. My problem is that I don't want to use prefetch_related or select_related so it will load all the users, as we might end up having thousands of users per each company! Also I don't want to load each latest user in a separate query so we end up having tens of queries per API request!
I've tried something like this:
users_qs = models.User.objects.filter(active=True).order_by('-created')
company_qs = models.Company.objects.prefetch_related(
Prefetch('users', queryset=users_qs[:1], to_attr='user')
).order_by('-created')
In this case, prefetch_related failed as we can't set limit on the Prefetch's queryset filter (it gives this error "Cannot filter a query once a slice has been taken.")
Any ideas?
I think you are providing an object instead of a queryset Prefetch('users', queryset=users_qs[:1], to_attr='user')

correctly fetch nested list in SQL

I have a design problem with SQL request:
I need to return data looking like:
listChannels:
-idChannel
name
listItems:
-data
-data
-idChannel
name
listItems:
-data
-data
The solution I have now is to send a first request:
*"SELECT * FROM Channel WHERE idUser = ..."*
and then in the loop fetching the result, I send for each raw another request to feel the nested list:
"SELECT data FROM Item WHERE idChannel = ..."
It's going to kill the app and obviously not the way to go.
I know how to use the join keyword, but it's not exactly what I want as it would return a row for each data of each listChannels with all the information of the channels.
How to solve this common problem in a clean and efficient way ?
The "SQL" way of doing this produces of table with columns idchannel, channelname, and the columns for item.
select c.idchannel, c.channelname, i.data
from channel c join
item i
on c.idchannel = i.idchannel
order by c.idchannel, i.item;
Remember that a SQL query returns a result set in the form of a table. That means that all the rows have the same columns. If you want a list of columns, then you can do an aggregation and put the items in a list:
select c.idchannel, c.channelname, group_concat(i.data) as items
from channel c join
item i
on c.idchannel = i.idchannel
group by c.idchannel, c.channelname;
The above uses MySQL syntax, but most databases support similar functionality.
SQL is made for accessing two-dimensional data tables. (There are more possibilities, but they are very complex and maybe not standardized)
So the best way to solve your problem is to use multiple requests. Please also consider using transactions, if possible.

What is the best way to merge 2 tables with Active Record and Mysql

We need to allow users to customize their entities like products... so my intention was to have a product table and a custom_product table with just the information the users are allowed to change.
When a client goes to the product I want to merge the information, means I want to merge the two tables - the custom overwrites the default Products table.
I know that in mysql there exists a ifnull(a.title, b.title) way but I was wondering if there is any nice and efficient way to solve this in Rails 4 with Active Record. Assume that the products and custom products table have just 2 columns, ID and TITLE
I think you can convert both objects to JSON and then handle their params as a hash, using the merge method:
class Product
end
class Customization
belongs_to :product
end
a = Product.find(...)
b = a.customization
c = JSON(a.to_json).merge(JSON(b.to_json).reject!{|k,v| v.nil?})
Therefore c will contain all params from Product eventually overridden by those in Customization which are not nil.
If you still want to use a Product object with hybrid values (taken from Customization) you can try this:
a.attributes = a.attributes.merge(b.attributes.reject!{|k,v| v.nil?})
In this case a will still be a Product instance. I would recommend to keep the same attributes in both models when doing this.

MySQL Join not Producing Desired Results

I'm working on writing a snippet for ModX that will find all document with the specified TV set to a user submitted value.
Here is a description of the tables I'm working with.
http://wiki.modxcms.com/index.php/Template_Variable_Database_Tables
Here is my query:
SELECT contentid
FROM prefix_site_tmplvar_contentvalues
JOIN prefix_site_tmplvar_contentvalues
ON prefix_site_tmplvars.id = prefix_site_tmplvar_contentvalues.tmplvarid
WHERE value="Red"
Currently it's producing results such as this:
http://pastebin.com/mEJ1w2be
Where each document ID will have a new row in the results for each Template Variable. So, for 7455 in the example there will be one array for the color="red" one for material="wood" one for size="small". Which, makes it difficult if I want to find a product that is red, small, and made of wood.
Is there a way that I could join these tables so that I could get one row per product with the document id and a set of template variable with associate values—not all broken up?
try
GROUP BY contentid
this will smush all the rows with the same contentid together.