I'm using PHP and I have the following two tables:
REVIEWS
| id | Item | editor_rating | user_votes |
------------------------------------------------
| 1 | item_1 | 18.1 | 415 |
| 2 | item_2 | 17.1 | 371 |
| 3 | item_3 | 14.7 | 111 |
| 8 | item_8 | 15.3 | 215 |
| 9 | item_9 | 17.7 | 119 |
| 10 | item_10 | 17.0 | 66 |
FILTERS
| id | Item | published |
----------------------------------
| 1 | item_1 | 1 |
| 2 | item_2 | 1 |
| 3 | item_3 | 1 |
| 8 | item_8 | 1 |
| 9 | item_9 | 1 |
| 10 | item_10 | 1 |
The following query works correctly and returns all the rows:
SELECT * FROM reviews AS r
JOIN filters AS f ON (r.id = f.id)
WHERE f.published = 1
So I'm on the right way.
Now I would like to do some math operations on the records. For example sum the fields editor_rating and user_votes and list the rows ordered by DESC. I tried the following but it returns uncorrect results (not MySQL error, a sum error):
SELECT *, r.editor_rating+r.user_votes AS total FROM reviews AS r
JOIN filters AS f ON (r.id = f.id)
WHERE f.published = 1 ORDER BY total DESC
The tables above contains the actual dB data. By summing editor_rating and user_votes I should have a list ordered as follows:
18.1 + 415 = 433.1 = Item_1
17.1 + 371 = 388.1 = Item_2
15.3 + 215 = 230.3 = Item_8
instead I get the following list:
Item_8
Item_9
Item_10
First check if these values is varchar then you have to cast it first :
SELECT *, cast(r.editor_rating as unsigned )+ cast(r.user_rating as unsigned ) AS total FROM reviews AS r JOIN filters AS f ON (r.id = f.id) WHERE f.published = 1 ORDER BY total DESC
It run for me when i cast it first to unsigned integer ..
Related
I have 2 tables.
SELECT * FROM purchases;
+------+---------+-----------+
|purid | total_q | dstatus |
+------+---------+-----------+
| 1 | 45 | DELIVERED |
| 2 | 50 | LOADING |
| 3 | 24 | DELIVERED |
| 4 | 15 | DELIVERED |
| 5 | 10 | DELIVERED |
+------+---------------------+
SELECT * FROM warehouse;
+------+-------+---------+
| wid | purid | total_q |
+------+-------+---------+
| 4 | 1 | 45 |
| 5 | 4 | 15 |
| 9 | 3 | 10 |
| 12 | 3 | 5 |
+------+-------+---------+
I want to get "delivered" purchases with its amounts which are not already included in warehouse table. Here is the demo where I stuck: DEMO
The query which I use is:
SELECT p.purid as purid, (p.total_q - IFNULL(w.total_q,0)) as ntq
FROM `purchases` as p
LEFT JOIN `warehouse` as w ON p.purid=w.purid
WHERE p.dstatus = "DELIVERED" AND (p.total_q - IFNULL(w.total_q,0)) > 0
My desired output:
+-------+------+
| purid | ntq |
+-------+------+
| 5 | 10 |
| 3 | 9 |
+------+-------+
The problem is I could not subtract "total_q (24) from purchases table" from "sum total_q(10+5) from warehouse table".
You can try to use subquery aggregate warehouse by purid before join otherwise you might get multiple rows.
Query #1
SELECT p.purid as purid,
p.total_q - IFNULL(w.total_q,0) as ntq
FROM `purchases` as p
LEFT JOIN (
SELECT purid,SUM(total_q) total_q
FROM warehouse
GROUP BY purid
) as w ON p.purid=w.purid
WHERE p.dstatus = "DELIVERED"
AND p.total_q - IFNULL(w.total_q,0) > 0;
purid
ntq
3
9
5
10
View on DB Fiddle
How can I write a single query that will give me SUM(Entrance.quantity) - SUM(Buying.quantity) group by product_id.
The problem is in rows that not exist in the first or second table. Is possible to do this?
Entrance:
+---+--------------+---------+
| id | product_id | quantity|
+---+--------------+---------+
| 1 | 234 | 15 |
| 2 | 234 | 35 |
| 3 | 237 | 12 |
| 4 | 237 | 18 |
| 5 | 101 | 10 |
| 6 | 150 | 12 |
+---+--------------+---------+
Buying:
+---+------------+-------------+
| id | product_id | quantity|
+---+------------+-------------+
| 1 | 234 | 10 |
| 2 | 234 | 20 |
| 3 | 237 | 10 |
| 4 | 237 | 10 |
| 5 | 120 | 15 |
+---+------------+------------+
Desired result:
+--------------+-----------------------+
| product_id | quantity_balance |
+--------------+-----------------------+
| 234 | 20 |
| 237 | 10 |
| 101 | 10 |
| 150 | 12 |
| 120 | -15 |
+--------------+-----------------------+
This is tricky, because products could be in one table but not the other. One method uses union all and group by:
select product_id, sum(quantity)
from ((select e.product_id, quantity
from entrance e
) union all
(select b.product_id, - b.quantity
from buying b
)
) eb
group by product_id;
SELECT product_id ,
( Tmp1.enterquantity - Tmp2.buyquantity ) AS Quantity_balance
FROM entrance e1
CROSS APPLY ( SELECT SUM(quantity) AS enterquantity
FROM Entrance e2
WHERE e1.product_id = e2.product_id
) Tmp1
CROSS APPLY ( SELECT SUM(quantity) AS buyquantity
FROM Buying b2
WHERE e1.product_id = b2.product_id
) Tmp2
GROUP BY Product_id,( Tmp1.enterquantity - Tmp2.buyquantity )
I have the below table about products:
| id | name | product_id | price | seller_id | discount_id |
--------------------------------------------------------------
| 1 | phone | 11 | 400 | 7 | 19 |
| 2 | cpu | 78 | 120 | 33 | 4 |
| 3 | phone | 11 | 380 | 8 | 22 |
| 4 | phone | 11 | 460 | 5 | 19 |
| 5 | memory | 80 | 45 | 12 | 16 |
| 6 | router | 98 | 115 | 7 | 16 |
| 7 | cpu | 78 | 115 | 33 | 66 |
I need to select all the columns of distinct product_id with the lowest price. Also to ORDER the result by price ASC. For this example:
| id | name | product_id | price | seller_id | discount_id |
--------------------------------------------------------------
| 5 | memory | 80 | 45 | 12 | 16 |
| 6 | router | 98 | 115 | 7 | 16 |
| 7 | cpu | 78 | 115 | 33 | 66 |
| 3 | phone | 11 | 380 | 8 | 22 |
I have no problems doing this using GROUP BY product_id and min(price) but I also need other columns (seller_id & discount_id)
MySQL version: 5.7.17
sql_mode=only_full_group_by
Table is temporary (ENGINE=MEMORY) and can't JOIN multiple times
How can I produce the result above from MySQL?
Add a subquery with the min price and join on min price and product.
SELECT id, name,product_id,price,seller_id,discount_id FROM t
JOIN
(SELECT tt.product_id,MIN(tt.price) minp FROM t as tt
GROUP BY tt.product_id)x
ON x.product_id=t.product_id AND x.price = t.price
Another option with LIMIT
SELECT * FROM T WHERE EXISTS
(SELECT 1 FROM T as TT ORDER BY TT.price ASC LIMIT 1
WHERE t.id= TT.id)
Given that the MEMORY engine is so restricting go the caveman way
SELECT SUBSTRING_INDEX(GROUP_CONCAT(id ORDER BY price),',',1),
SUBSTRING_INDEX(GROUP_CONCAT(name ORDER BY price),',',1),
product_id,MIN(price),
SUBSTRING_INDEX(GROUP_CONCAT(seller_id ORDER BY price),',',1),
SUBSTRING_INDEX(GROUP_CONCAT(discount_id ORDER BY price),',',1) FROM t
GROUP BY product_id
You can join the table with itself (on product_id). As a join-condition add left.price > right.price - and then choose the rows, where right.price is null, because for that join, there is no lower right price, meaning the one you have left is the lowest:
SELECT l.id, l.name, l.product_id, l.price, l.seller_id, l.discount_id
FROM
products l
LEFT JOIN
products r
on
l.product_id = r.product_id AND l.price > r.price
WHERE
isnull (r.price) -- that means: no cheaper price for this position.
intermediate result (SELECT * no WHERE) would look like (shortened):
| l.id | l.name | l.product_id | l.price | r.id | r.name | r.product_id | r.price
| 3 | phone | 11 | 380 | null | null | null | null
| 4 | phone | 11 | 460 | 3 | phone | 3 | 380
Side node: For very large datasets there might be performance-issues, because every additional line of a component would add multiple result rows. i.e. consider another phone:
| l.id | l.name | l.product_id | l.price | r.id | r.name | r.product_id | r.price
| 3 | phone | 11 | 380 | null | null | null | null
| 4 | phone | 11 | 460 | 3 | phone | 3 | 380
| 5 | phone | 11 | 500 | 3 | phone | 3 | 380
| 5 | phone | 11 | 500 | 4 | phone | 3 | 460
So, if you want to get the lowest price in the past 60 days with daily changes, that will be a huge amount of rows just for "that"... (Actually 60+59+58+...+2+1 I think, cause the most expensive price will produce 59 comparision rows and so on)
I have two tables (PO and GRN).
I want to get:
[This is what I am doing:][1] http://sqlfiddle.com/#!9/db000/2
I get these results (wrong po_qty , GRN_qty and GRN_balance ).
What I am expecting is:
| Item | PONO | po_qty | GRN_qty | GRN_balance |
|------|------|--------|---------|-------------|
| A | po1 | 70 | 65 | 5 |
| B | po1 | 50 | 0 | 50 |
| C | po2 | 10 | 5 | 5 |
| D | po3 | 20 | 0 | 20 |
| A | po4 | 15 | 10 | 5 |
Here is a way of doing it
select
p.Item,
p.PONO,
sum(p.Qty) as po_qty,
coalesce(g.GRN_qty,0) ,
sum(p.Qty) - coalesce(g.GRN_qty,0) as GRN_balance
from PO p
left join (
select PONO,Item,sum(Qty) as GRN_qty from GRN
group by PONO,Item
)g
on g.PONO = p.PONO and g.Item = p.Item
group by p.Item,p.PONO
order by p.PONO
http://sqlfiddle.com/#!9/db000/30
I modified your SQL. Please execute and see
SELECT PO.Item,PO.PONO,
PO.Qty as po_qty,
GRN.Qty as GRN_qty,
PO.Qty- GRN.Qty as GRN_balance
from PO,GRN
group by PO.Item
Thank you..
i'm build an exercises web app and i'm working with two tables like this:
Table 1: weekly_stats
| id | code | type | date | time |
|----|--------------|--------------------|------------|----------|
| 1 | CC | 1 | 2015-02-04 | 19:15:00 |
| 2 | CC | 2 | 2015-01-28 | 19:15:00 |
| 3 | CPC | 1 | 2015-01-26 | 19:15:00 |
| 4 | CPC | 1 | 2015-01-25 | 19:15:00 |
| 5 | CP | 1 | 2015-01-24 | 19:15:00 |
| 6 | CC | 1 | 2015-01-23 | 19:15:00 |
| .. | ... | ... | ... | ... |
Table 2: global_stats
| id | exercise_number |correct | wrong |
|----|-----------------|--------|-----------|
| 1 | 138 | 1 | 0 |
| 2 | 246 | 1 | 0 |
| 3 | 988 | 1 | 10 |
| 4 | 13 | 5 | 0 |
| 5 | 5 | 4 | 7 |
| 6 | 5 | 4 | 7 |
| .. | ... | ... | ... |
What i would like is to get MAX(correct-wrong) and MIN(correct-wrong) and now i'm working with this query:
SELECT
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MAX(correct - wrong) from global_stats)
UNION
SELECT
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MIN(correct - wrong) from global_stats);
This query is working good, except for one thing: when "WHERE correct - wrong = (SELECT MIN(correct - wrong)[...]" selects more than one row, the row selected is the first but i would like to have returned the most recent (in other words: ordered by datetime(date, time)). Is it possible?
Thanks!
I think you can solve it like this:
SELECT * FROM (
SELECT
1 as sort_column,
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MAX(correct - wrong) from global_stats)
ORDER BY date DESC, time DESC
LIMIT 1 ) as a
UNION
SELECT * FROM (
SELECT
2 as sort_column,
exercise_number,
date,
time
FROM weekly_stats AS w JOIN global_stats AS g
ON w.id=g.id
WHERE correct - wrong = (SELECT MIN(correct - wrong) from global_stats)
ORDER BY date DESC, time DESC
LIMIT 1) as b
ORDER BY sort_column;
Here is the documentation about how UNION works.