Alias table doesn't exist in where statement - mysql

The question is from https://code.dennyzhang.com/sales-analysis-i
My solution is:
select seller_id
from (select seller_id, sum(price) price
from Sales
group by seller_id) S
# where S.price = max(S.price)
where S.price = (select max(price) from S)
However, the console gives me the error message:
Table 'test.s' doesn't exist
I replaced the last line of code by
where S.price = 0
This doesn't give me any error messages meaning that S table does exist. So my question is how does this error message come from?

S is a reference to a table that can be used to qualify columns. It cannot be used in a FROM clause.
You can do what you want using a CTE:
with S as (
select seller_id, sum(price) as price
from Sales
group by seller_id
)
select seller_id
from S
where S.price = (select max(price) from S)

Related

Mysql query to get lowest value from multiple conditions using UNION operator

I have price table with three columns:
id, price, product_id.
product_id can contain multiple prices.
I need to get lowest price product_id when query perform in mysql.
I am using multiple conditions using UNION operator in this table data is coming but results are wrong.
In this table product_id 101 has 4999 but I am getting 5000, even I have set order by price ASC
Here is my mysql fiddle link
mysql fiddle
This is very basic SQL.
select product_id, min(price) as price
from price
group by product_id;
To fetch minimum prices per product for a given range add them to case statement in group by clause:
select product_id, min(price) as price
from price
group by product_id, case when price between 100 and 5000 then 1 else 2 end;
SQL fiddle
Assuming you need the ID of each record with the min price.
Select p.* from price p
INNER JOIN (Select product_ID, Min(Price) as price from `price` group by Product_ID) sub
on sub.product_Id = p.product_Id
and sub.price = p.price
SQL FIDDLE
Otherwise...
Select product_ID, Min(Price) as price from `price` group by Product_ID
SQL FIDDLE
---- UPDATE----
Still not sure I understand the question... which is why I asked for expected output given your data. I may be able to infer the requirements which i'm not getting. As it stands I had NO idea why a union was needed, nor how this "grouping" came into play.
SELECT p.* from price p
INNER JOIN (Select product_ID, Min(Price) as price from `price` group by Product_ID) sub
on sub.product_Id = p.product_Id
and sub.price = p.price
SQL Fiddle
Assuming no overlap of product_ID in ranges...
SELECT pr.id,MIN(pr.price),pr.product_id FROM price pr WHERE pr.price >= 100 AND pr.price <= 5000 group by pr.product_id UNION SELECT pr.id,MIN(pr.price),pr.product_id FROM price pr WHERE pr.price >= 5001 AND pr.price <= 10000 group by pr.product_id

MySql - SUM() of column in child table (1:n) in a Sub-query/Outer Join using LIMIT

I have two tables - PRODUCT, ACTIVITY. Each product can have multiple activity (1:n). Each activity has an (INT) action column. I need to query all the products and the SUM(product.action) of the 10 most recent activities.
My first attempt was to use a sub-query:
select p.*, (select sum(a.action) from activity a
where a.product_id = p.product_id
order by a.timestamp desc limit 10) recent
from product p
However, the result was incorrect. I realized that the sub-query wasn't using the LIMIT and was returning the SUM() of all ACTIVITY records matching the product_id.
My second attempt was to follow the advice here and wrap the sub-query in another select query:
select p.*, (select sum(temp.action) as recent
from (select a.action from activity a
where a.product_id = p.product_id
order by a.timestamp desc limit 10) temp)
from product p
However, I got the error message
Error Code: 1054. Unknown column 'p.product_id' in 'where clause'. I found a related question here and realized that MYSQL doesn't support alias on 2nd level nesting. I didn't quite follow the answer for that question.
I also tried an outer join
select p.*, sum(temp.action) as recent
from product p
left join
(select a.product_id, a.action from activity a
where a.product_id = p.product_id
order by a.timestamp desc limit 10) temp
on p.product_id= temp.product_id
Again, I ran into the same issues:
The LIMIT is not enforced
The alias is not recognized
How do I fix this?
1- Get distinct products from your product table
2- Get the ten most recent activities for each product
3- Get sums from (2)
4- Join
Take a look at Using LIMIT within GROUP BY to get N results per group?. It sounds similar to what you need for (2).
EDIT
I modified the query slightly and tested it on a small dataset. The previous version did not work because the where clause was in the wrong place. See below.
select t.product_id, sum(t.action) from
(
select product_id, action, timestamp,
#row_num := if(#prev = product_id, #row_num + 1, 1) as row_num, #prev := product_id
from activity
join (select #prev := null, #row_num := 0) as vars
order by product_id, timestamp desc
) as t
where t.row_num <= 10
group by t.product_id;

SQL - Does row match max of sums

I am getting a little tripped up with a SQL query. Here is some background.
Schema:
Product(pid, price, color),
Order(cid, pid, quantity),
Customer(cid, name, age)
I want to get the pid of the most ordered product (greatest quantity).
I have managed to determine the max value with:
Select Max(total)
From (Select Sum(quantity) as total
From Orders Group By pid) as Totals
but I am getting stuck trying to match which products are in this subquery. Here is what I have tried:
Select pid, SUM(quantity) as q
From Orders
Where q in (
Select Max(total)
From (Select Sum(quantity) as total
From Orders
Group By pid) as Totals
)
Group By pid
This says that q is an unknown column.
Any suggestions on how I could do this or do it better?
you can do a JOIN along with GROUP BY like
select p.*
from product p
join
(select pid from Order
group by pid having quantity = max(quantity)
) tab on p.pid = tab.pid;
In your posted query it's erroring q is an unknown column cause q is a column alias which you are trying to use in WHERE condition; which is not allowed.
You should be able to simply include the PID in the original query because you are grouping on it. Then ORDER BY and and get only the top result using LIMIT 1.
SELECT
pid
,Sum(quantity) as total
FROM
Orders
GROUP BY
pid
ORDER BY
Sum(quantity)
LIMIT 1
Here's one way you can do it using a subquery with limit:
select o.pid, sum(o.quantity)
from `order` o
group by o.pid
having sum(o.quantity) =
(
select sum(quantity)
from `order`
group by pid
order by sum(quantity) desc
limit 1
)
SQL Fiddle Demo
If you want only one most ordered product, then Karl's answer is fine. If you want all that have the same quantity, then:
select pid, sum(quantity) as quantity
from orders o
group by pid
having sum(quantity) = (select max(quantity)
from (select sum(quantity) as quantity
from orders o
group by pid
) q
);

select unique data from a table with similar id data field

I am trying to retrieve unique values from the table above (order_status_data2). I would like to get the most recent order with the following fields: id,order_id and status_id. High id field value signifies the most recent item i.e.
4 - 56 - 4
8 - 52 - 6
7 - 6 - 2
9 - 8 - 2
etc.
I have tried the following query but not getting the desired result, esp the status_id field:
select max(id) as id, order_id, status_id from order_status_data2 group by order_id
This is the result am getting:
How would i formulate the query to get the desired results?
SELECT o.id, o.order_id, o.status_id
FROM order_status_data2 o
JOIN (SELECT order_id, MAX(id) maxid
FROM order_status_data2
GROUP BY order_id) m
ON o.order_id = m.order_id AND o.id = m.maxid
SQL Fiddle
In your query, you didn't put any constraints on status_id, so it picked it from an arbitrary row in the group. Selecting max(id) doesn't make it choose status_id from the row that happens to have that value, you need a join to select a specific row for all the non-aggregated columns.
Like so:
select d.*
from order_status_data2 d
join (select max(id) mxid from order_status_data2 group by order_id) s
on d.id = s.mxid
Try this Query.This will help you
SELECT id ,orderid,statusid
FROM table_name
WHERE id IN
(
SELECT max(id) FROM table_name GROUP BY orderid
)
ORDER BY statusid
You can refer this Sql_Fiddle_link which uses your example.

select last record from a relation

I have this situation. I have a table Orders that is related to OrderStatus.
OrderStatus
id | orderId | created
I need to retrieve the Orders with its last status. I tried this query, what I don't know if it is performant. I need to know if there are better solutions.
select Orders.id, OrderStatus.status from Orders
inner join OrderStatus on OrderStatus.id =
(select top 1 id from OrderStatus where orderId = Order.id order by created desc)
Correlated subquery is usually bad news (sometimes SQL Server can optimize it away, sometimes it acts like a really slow loop). Also not sure why you think you need DISTINCT when you're only taking the latest status, unless you don't have any primary keys...
;WITH x AS
(
SELECT o.id, os.status,
rn = ROW_NUMBER() OVER (PARTITION BY os.orderId ORDER BY created DESC)
FROM dbo.Orders AS o
INNER JOIN dbo.OrderStatus AS os
ON o.id = os.orderId
)
SELECT id, status
FROM x
WHERE rn = 1;
You can use the Row_Number function:
WITH CTE AS
(
SELECT Orders.id, OrderStatus.status,
RN = ROW_NUMBER() OVER (
PARTITION BY OrderStatus.OrderId
ORDER BY created DESC)
FROM Orders
INNER JOIN OrderStatus ON OrderStatus.OrderId = Orders.id
)
SELECT id, status
FROM CTE WHERE RN = 1
I've used a common-table-expression since it enables to filter directly and it's also very readable.