I have a DB with tables for product, price and seller. The prices for each product is ranked (lowest price is Price.rank = 1, second lowest price is Price.rank = 2 etc.). I'm trying to create a query where I get a list of prices for a product, but where I filter out prices from certain sellers if they have a rank of below x. The problem is that when I apply the filter as set out below, it filters out prices based on the Price.rank filter also for sellers that are not in the EXCLUDE_LIST.
How can I apply the Price.rank filter in a way that it applies only for those that are in the EXCLUDE_LIST?
EXCLUDE_LIST = ['Seller_1' , 'Seller_2']
query = db.session.query(Price, Seller, Product)
# joins intentionally left out
query = query.filter(Product.id = 1))
query = query.filter((Seller.name.notin_(EXCLUDE_LIST)) & (Price.rank < 3))
prices = query.all()
Related
I am creating a spare part management database in Microsoft Access. I have two table which are ItemTable and EntryTable. ItemTable holds information about each item with unique ItemID and EntryTable holds information of each items usage. I need to calculate the total stock left for each items based on the usage.
So as you can see, for the ItemID with 2, i need to calculate the total stock left based on the usage of In or Out of Status field.
If status is In then plus elseif status is Out then minus. Then total the stock of ItemID 2. Thus the total stock for ItemID 2 will be 3. I have figured out by total and group by for the ItemID but i cannot figure out the way to subtotal based on condition from other column. Thank you.
You can do it with conditional aggregation:
select itemid,
sum(iif(status = 'In', 1, -1) * quantity) as total
from entrytable
group by itemid
I have a product list model and would like to know the ranking of a specific price of this model.
sorted_product_list = Product.objects.all().order_by('-price')
my_product = {'id': 10, 'price': 20000}
django has RowNum class but it is not support for mysql
i have only one idea that use enumerate
for rank, element in enumerate(sorted_product_list):
if element.id == my_product.id:
my_product_rank = rank
Is there any other solution?
We can obtain the rank by Counting the number of Products with a higher price (so the ones that would have come first), so:
rank = Product.objects.filter(price__gt=myproduct['price']).count()
Or in case we do not know the price in advance, we can first fetch the price:
actual_price = Product.objects.values_list('price', flat=True).get(id=myproduct['id'])
rank = Product.objects.filter(price__gt=actual_price).count()
So instead of "generating" a table, we can filter the number of rows above that row, and count it.
Note that in case multiple Products have the same price, we will take as rank the smallest rank among those Products. So if there are four products with prices $ 200, $ 100, $100, and $ 50, then both Products with price $ 100 will have rank 1. The Product that costs $ 50 will have rank 3. In some sense that is logical, since there is no "internal rank" among those products: the database has the freedom to return these products in any way it wants.
Given there is an index on the price column (and it is a binary tree), this should work quite fast. The query will thus not fetch elements from the database.
In case the internal rank is important, we can use an approach where we first determine the "external rank", and then iterate through Products with the same price to determine the "internal rank", but note that this does not make much sense, since between two queries, it is possible that this "internal order" will change:
# rank that also takes into account *equal* prices, but *unstable*
actual_price = Product.objects.values_list('price', flat=True).get(id=myproduct['id'])
rank = Product.objects.filter(price__gt=actual_price).count()
for p in Product.objects.filter(price=actual_price):
if p.id != myproduct['id']:
rank += 1
else:
break
we thus keep incrementing while we have not found the product, in case we have, we stop iterating, and have obtained the rank.
Although I can get the joins to work, it doesn't return the lowest deal possible. The result should be lowest handset price possible with the lowest monthly cost. Currently I can get the lowest handset price, but not with the lowest monthly cost and similarly lowest monthly cost but not with the lowest priced handset.
I have 3 tables DEALS, TARIFFS and HANDSETS. When a customer comes to a manufacturer product listing page, it loads all products related to that manufacturer (in most instances around 40 products). What I would like is it to load the cheapest deal available for each product. Tariff table has over 4000 records. Handset table has over 3000 records. Deals table has over 1 million records.
There is a representation of the the 3 tables below with relevant columns:
Handset Table
==================================
id | manufacturer_id
-----------------------------------
100 1
Deals Table
==================================================
tariff_id | handset_id | handset_cost
--------------------------------------------------
15 100 44.99
20 100 114.99
Tariffs Table
==============================
id | monthly_cost
------------------------------
15 12.50
20 7.50
This is the query
$this->db->select('h.name, t.monthly_cost, d.handset_cost');
$this->db->from('aff_deals d');
$this->db->join('aff_tariffs t', 't.id = d.tariff_id', 'inner');
$this->db->join('aff_handsets h', 'h.id = d.handset_id', 'inner');
if (isset($manuid)) {
$this->db->where('h.manufacturer_id', $manuid);
}
$this->db->order_by('d.handset_cost ASC');
$this->db->order_by('t.monthly_cost ASC');
$this->db->group_by('h.name');
$query = $this->db->get();
$result = $query->result();
Unfortunately this returns handset cost of £114.99 and monthly cost of £7.50, when I need £44.99 and £12.50. The example above is a simple snap shot. I have tried MIN(d.handset_cost), sub-queries but cannot get the desired results. Somehow I need to be able to get the lowest price handsets, even if it's 0.00 (FREE), with its equivalent monthly cost. Any help would be most welcome.
According to your query you are misusing Mysql's GROUP BY extension without having any aggregate function this will lead your query to return indeterminate results for columns which are absent in group by taking your query as an example,columns t.monthly_cost, d.handset_cost values are indeterminate if you are specific to pick minimum row from deals table per handset then you can use below query
SELECT h.name,
t.monthly_cost,
d.handset_cost
FROM aff_deals d
INNER JOIN (SELECT handset_id,MIN(handset_cost) handset_cost
FROM aff_deals
GROUP BY handset_id) dd
ON d.handset_id = dd.handset_id AND d.handset_cost = dd.handset_cost
INNER JOIN aff_tariffs t ON t.id = d.tariff_id
INNER JOIN aff_handsets h ON h.id = d.handset_id
WHERE h.manufacturer_id =1
ORDER BY d.handset_cost ASC,t.monthly_cost ASC
See Demo
For active record query it will difficult to replicate above (subselect) query bu you can directly run this query through $this->db->query('your query')
I have a Products table and a ProductionReport table in my database.
The ProductionReport table captures weekly production information for each product. My app will report on this information.
Table structures
ProductionReport
productionreportid, productid, date, qty
1, 1, 2013-04-08, 50
2, 2, 2013-04-08, 12
Products
productid, productname
1, Skin cream
2, Peanut Oil
3, Bath Salts
4, Shampoo
My page uses a gridview that will list all products (SELECT productid, productname FROM Products) and join in the ProductionReport table so as to display a list of all products and production values for the week that user can update.
My problem is the sql query to populate the GridView. It currently only gets rows where there is a joined value in both tables:
SELECT pro.productname, pr.productionreportid, IFNULL(pr.qty, 0) qty
FROM Products pro
LEFT JOIN ProductionReport pr ON pro.productid = pr.productid
WHERE DATE(pr.date) = '2013-04-08'
So, given the above described data, I'm expecting to get the following resultset back
Skin Cream, 1, 50
Peanut Oil, 2, 12
Bath Salts, 0, 0
Shampoo, 0, 0
Unfortunately, all I'm getting back is the first 2 rows. I believe that's because of the WHERE clause targeting a column in the joined table. If that's the case, it's clearly a serious flaw in my logic, but I don't know what to do about it.
Any suggestions?
Try this
SELECT
pro.productname,
pr.productionreportid,
IFNULL(pr.qty, 0) qty
FROM
Products pro
LEFT JOIN ProductionReport pr
ON pro.productid = pr.productid
AND DATE(pr.date) = '2013-04-08'
Basically move the date condition from WHERE clause to the JOIN clause
You are correct in that DATE(pr.date) = '2013-04-08' won't match if pr.date is null.
You can change it to something like pr.date is null or date(pr.date) = '2013-04-08'
There is something wrong with this MySQL code.
it seems to be returning more stock then there should be.
table positions holds the stock available (multiple positions one product)
table orderbody holds the orders ordered products (1 orderheader to many orderbody)
SELECT PRO.ProductID,
PRO.ProductCode,
SUM( POS.Qty ) AS instock,
SUM( OB.Qty ) AS onorder
FROM products AS PRO
LEFT JOIN position AS POS ON POS.ProductID = PRO.ProductID
LEFT JOIN orderbody AS OB ON OB.ProductID = PRO.ProductID
WHERE POS.ProductID = OB.ProductID
GROUP BY PRO.ProductID, POS.ProductID, OB.ProductID
i'm getting instock 320
actual stock quantity = 40
number of positions = 2 (qty 20 each)
onorder = 16 qty
actual number of orderbody = 8 rows
actually on order = 8 (each with qty = 1)
this is on one of the products
i know it has something to do with the group by but i cant work it out.
Appreciate any help received.
I had the same problem a few days ago. Try it by SELECTing from a separate query: SELECT ... FROM products, (SELECT...)..." where you have the two tables to be left joined. try to test the sub-query by itself first, and try to put it together once ot works. (once you have the data you want, and not duplicates, because that is you problem.
you are selecting this field PRO.ProductCode, but not grouping by it, at a guess it might be the problem.