MAX aggregate function with VIEW - mysql

I have this query :
CREATE VIEW MOSTACTIVESELLER AS
Select a.* from
(
SELECT a.ownerID, b.sellerName, count(distinct a.ITEMID) as item_qty
FROM item AS a
INNER JOIN seller AS b ON a.ownerID = b.sellerID
GROUP BY a.ownerID,b.sellerName
) a
the resutl of this view query is:
+--ID--+--seller-+-qty--+
| 1000 | Nick | 3 |
| 1001 | Morgan | 2 |
| 1002 | stancly | 1 |
| 1003 | chandler | 1 |
| 1004 | chiptle | 3 |
| 1005 | samir | 2 |
| 1006 | matuidi | 3 |
| 1007 | medjek | 1 |
| 1008 | leo | 1 |
| 1009 | georgi | 1 |
| 1010 | bocheli | 2 |
+------+----------+---+
So what I want is use an aggregate function like max to return only the most active seller in this list(ONLY 1) as you can see 3 sellers with qty 3 , i think that max function will return one . if not i maybe order the view DESC and return the top value. but could not make that to work. I tried to use max with the view MOSTACTIVESELLER i dont know how to do that??

I'm surprised your query works in MySQL -- usually subqueries are not allowed in the FROM clause in a view. But this should work as a view:
CREATE VIEW MOSTACTIVESELLER AS
SELECT s.sellerID, s.sellerName, count(distinct i.ITEMID) as item_qty
FROM item i INNER JOIN
seller s
ON i.ownerID = s.sellerID
GROUP BY s.sellerID, s.sellerName
HAVING count(distinct i.ITEMID) = (SELECT count(distinct i.ITEMID)
FROM item i
GROUP BY i.ownerID
ORDER BY 1 DESC
LIMIT 1
);
EDIT:
I thought LIMIT was allowed with =, but MySQL has strange limits on the use of LIMIT in a subquery. It is easy enough to replace:
HAVING count(distinct i.ITEMID) >= ALL (SELECT count(distinct i.ITEMID)
FROM item i
GROUP BY i.ownerID
);

Related

Get max value by priority when specific column is not null

I have database table like
transactions
-----------
id
code
date
amount
formalities
-----------
id
transaction_id
this is query to get max value of transactions
SELECT MAX(transaction_id) FROM `transactions` n LEFT JOIN `formalities` r ON r.transaction_id = n.id
But what I want to achieve here is to get the max value of id group by transactions code, but the value must check if the transactions have relation to formalities or not.
If yes, get max value where they relate.
If not just get the usual max value.
Is there a query to achieve something like this?
example:
transactions
--------------------
id | code | amount |
1 | ABC | 10000 |
2 | ABC | 20000 |
3 | KOO | 10000 |
4 | ABC | 20000 |
5 | KOO | 30000 |
6 | KOO | 10000 |
formalities
-----------
id | transaction_id |
1 | 3 |
2 | 5 |
The result I want is getting the following output from the transactions table
id
--
4
5 ( priority the one that have relation and get the max value)
Use a LEFT JOIN and get both - MAX(transactions.id) and MAX(formalities.transaction_id):
select t.code, max(f.transaction_id), max(t.id)
from transactions t
left join formalities f on f.transaction_id = t.id
group by t.code
The result would be
| code | max(f.transaction_id) | max(t.id) |
| ---- | --------------------- | --------- |
| ABC | NULL | 4 |
| KOO | 5 | 6 |
View on DB Fiddle
To "prioritize" transaction_id column from formalities table you can use COALESCE(), which will return the first non NULL value:
select t.code, coalesce(max(f.transaction_id), max(t.id)) as max_transaction_id
from transactions t
left join formalities f on f.transaction_id = t.id
group by t.code
Result:
| code | max_transaction_id |
| ---- | ------------------ |
| ABC | 4 |
| KOO | 5 |
View on DB Fiddle
I am not sure if I am getting the question right, but why don't you simply use -
SELECT MAX(transaction_id) FROM `transactions` n INNER JOIN `formalities` r ON r.transaction_id = n.id group by n.code

How to ORDER BY CALCULATED SUM with Another Table in MySQL

For example, I have 2 table 'meta' and 'log'
in meta table:
| type | score |
|------|-------|
| a | 1 |
| b | 2 |
| c | 3 |
in log table:
| log_id | log_type | object_id |
|--------|----------|-----------|
| 1 | a | 13 |
| 2 | b | 13 |
| 3 | a | 14 |
| 4 | c | 14 |
| 5 | b | 15 |
| 6 | c | 15 |
so we know:
object 13 got score: a+b = 3
object 14 got score: a+c = 4
object 15 got score: b+c = 5
I want to query log table group by object id and order by sum of object score, is it possible?
select log.object_id, sum(meta.score)
from log
left join meta on meta.type = log.log_type
group by log.object_id
order by sum(meta.score) desc
This will produced the desired output
SELECT object_id, sum(score) from log
INNER JOIN meta on meta.type = log.log_type group by object_id ORDER BY sum(score);
But have you got the correct table design? You need to join on the meta.type and log.log_type column but this implies that if the log_type is 'a' the value of 3 is common for all object_ids is this really what you want?
Try this
Select object_id,sum(score) as c FROM `log` as a INNER JOIN `meta` as b on a.log_type=b.type group by object_id order by c desc
SELECT log.object_id, sum(score) total_score
FROM meta
INNER JOIN log on meta.type = log.log_type
GROUP BY log.object_id

MySQL select unique rows in two columns with the highest value in one column

I have a basic table:
+-----+--------+------+------+
| id, | name, | cat, | time |
+-----+--------+------+------+
| 1 | jamie | 1 | 100 |
| 2 | jamie | 2 | 100 |
| 3 | jamie | 1 | 50 |
| 4 | jamie | 2 | 150 |
| 5 | bob | 1 | 100 |
| 6 | tim | 1 | 300 |
| 7 | alice | 4 | 100 |
+-----+--------+------+------+
I tried using the "Left Joining with self, tweaking join conditions and filters" part of this answer: SQL Select only rows with Max Value on a Column but some reason when there are records with a value of 0 it breaks, and it also doesn't return every unique answer for some reason.
When doing the query on this table I'd like to receive the following values:
+-----+--------+------+------+
| id, | name, | cat, | time |
+-----+--------+------+------+
| 1 | jamie | 1 | 100 |
| 4 | jamie | 2 | 150 |
| 5 | bob | 1 | 100 |
| 6 | tim | 1 | 300 |
| 7 | alice | 4 | 100 |
+-----+--------+------+------+
Because they are unique on name and cat and have the highest time value.
The query I adapted from the answer above is:
SELECT a.name, a.cat, a.id, a.time
FROM data A
INNER JOIN (
SELECT name, cat, id, MAX(time) as time
FROM data
WHERE extra_column = 1
GROUP BY name, cat
) b ON a.id = b.id AND a.time = b.time
The issue here is that ID is unique per row you can't get the unique value when getting the max; you have to join on the grouped values instead.
SELECT a.name, a.cat, a.id, a.time
FROM data A
INNER JOIN (
SELECT name, cat, MAX(time) as time
FROM data
WHERE extra_column = 1
GROUP BY name, cat
) b ON A.Cat = B.cat and A.Name = B.Name AND a.time = b.time
Think about it... So what ID is mySQL returning form the Inline view? It could be 1 or 3 and 2 or 4 for jamie. Hows does the engine know to pick the one with the max ID? it is "free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. " it could pick the wrong one resulting in incorrect results. So you can't use it to join on.
https://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html
If you want to use a self join, you could use this query:
SELECT
d1.*
FROM
date d1 LEFT JOIN date d2
ON d1.name=d2.name
AND d1.cat=d2.cat
AND d1.time<d2.time
WHERE
d2.time IS NULL
It is very simple
SELECT MAX(TIME),name,cat FROM table name group by cat

MySQL query: select records with highest value in group

I have a MySQL table like this.
| season_id | round_1 | names | score_round_1
| 5 | 10 | John1 | 5
| 5 | 10 | John2 | 3
| 5 | 11 | John3 | 2
| 5 | 11 | John4 | 5
I want to select the records with highest score_round_1 in each round_1(10,11) group .
In this case the first and last rows would be selected.
I tried using the GROUP BY round_1 but that only returns the first row from the two.
Any advice?
Zolka
This is simple
select max(score_round_1),
name
from score
group by round_1
SELECT *
FROM table p1
WHERE score_round_1 = (
SELECT MAX( p2.score_round_1 )
FROM table p2
WHERE p1.round_1 = p2.round_1 ) ANDround_1 !=0
Use aggregate function MAX
SELECT names, MAX(score_round_1) GROUP BY round_1

Select only newest grouped entries

I have a table with data like this:
+-----------+-------+------+----------+
| timestamp | event | data | moreData |
+-----------+-------+------+----------+
| 100000000 | 1 | 10 | 20 |
| 100000001 | 1 | 15 | 10 |
| 100000002 | 1 | 30 | 30 |
| 100000003 | 1 | 5 | 50 |
| 100000004 | 2 | 110 | 120 |
| 100000005 | 2 | 115 | 110 |
| 100000006 | 2 | 130 | 130 |
| 100000007 | 2 | 15 | 150 |
+-----------+-------+------+----------+
Now I want to select only the newest rows for each event. So in the end I want to have this result set:
+-----------+-------+------+----------+
| timestamp | event | data | moreData |
+-----------+-------+------+----------+
| 100000003 | 1 | 5 | 50 |
| 100000007 | 2 | 15 | 150 |
+-----------+-------+------+----------+
So far I was not able to do this. In MySQL I can use "GROUP BY event" but then I get some random row from the database, not the newest. ORDER BY doesn't help because the grouping is done before ordering. Using an aggregation like MAX(timestamp) while grouping by event also doesn't help because then the timestamp is the newest but "data" and "moreData" is still from some other random row.
I guess I have to do a sub select so I have to first get the latest timestamp like this:
SELECT MAX(timestamp), event FROM mytable GROUP BY event
and then use the result set to filter a second SELECT, but how? And maybe there is a clever way to do it without a sub select?
AFAIK, sub select is your best option, as follows:
SELECT *
FROM mytable mt
JOIN ( SELECT MAX(timestamp) as max, event
FROM mytable
GROUP BY event) m_mt
ON (mt.timestamp = m_mt.max AND mt.event = m_mt.event);
You could use an inner join as a filter:
select *
from events e1
join (
select event
, max(timestamp) as maxtimestamp
from events
group by
event
) e2
on e1.event = e2.event
and e1.tiemstamp = e2.maxtimestamp
SELECT * FROM
(SELECT * FROM mytable ORDER BY timestamp DESC) AS T1
GROUP BY event;
SELECT e2.*
FROM events e
JOIN events e2 ON e2.event = e.event AND e2.timestamp = MAX(e2.timestamp)
GROUP BY e.id