ID of the longest string in "group by" - mysql

How do I get the id of MAX(name)? The id I get from below query doesn't correspond to the row where MAX(name) is in.
SELECT id, MAX(name) from table group by country
id name country
+---+-----------+---------+
| 1 | John | USA |
+---+-----------+---------+
| 2 | Joe | CHINA |
+---+-----------+---------+
| 3 | Jonah | USA |
+---+-----------+---------+
| 4 | Jonathan | USA |
+---+-----------+---------+
Edit:
The purpose is to get the longest name in every country. So from the table, I'd like to see the result to be id 2 and 4.

You can do it with variables, and self joins, and depending on your version of sql window functions, but you can also do some string manipulation.
SELECT country,
SUBSTRING_INDEX(ids, ',', 1) AS id
FROM (
SELECT country,
GROUP_CONCAT(id ORDER BY LENGTH(NAME) DESC) AS ids
FROM table
GROUP BY country
) z
Also, max(name) won't get you the one with the longest name, it will get you the one closest to the end of the alphabet.
You can also try (assuming you need to account for the possibility of more than one name per country having the same max length):
SELECT z.country, z.id
FROM table z
JOIN (
SELECT country, MAX(LENGTH(name)) AS maxLen
FROM table
GROUP BY country
) lens ON (lens.country = z.country AND lens.maxLen = LENGTH(z.name))

Use a subselect:
SELECT id, country
FROM table
WHERE (country, CHAR_LENGTH(name)) IN (SELECT country, MAX(CHAR_LENGTH(name))
FROM table
GROUP BY country)
GROUP BY country
Note, however, that there may be more than one row returned if there are more than one records having this length of the name!

Related

Group by names desc - get last entered values for a grouped name

I have an table like that:
id | name | v (lvl)
11 | Jane | 6
12 | John | 5
13 | Jane | 6
14 | John | 5
15 | Jane | 7
16 | Jane | 5
In my autocomplete form now id like to group the names but get the last value (value with biggest id). In the example above would be
Jane | 5
I tried with combinations like distinct, group by, order by. But im always get
Jane | 6
or grouped like this and reversed:
Jane | 6
Jane | 7
Jane | 5
I would need something like this:
SELECT name,lvl FROM
(
SELECT DISTINCT name, lvl FROM pora WHERE name LIKE 'Jane' ORDER BY lvl DESC
)
GROUP BY name
EDIT: I won't get the highest lvl, i want get the lvl of the highest id, grouped by name. Thats all. My example above would be the best explanation what i like to get.
In the inner query i change the order to DESC for all and in the outer i group it by names. But i get an error for this.
EDIT 2 I finally did at my own. The correct solution (i was already close):
SELECT a.name, a.lvl FROM
(
SELECT DISTINCT name, lvl FROM pora WHERE name LIKE 'Jane' ORDER BY id DESC
)as a
GROUP BY name
LIKE without % is just =
SELECT *
FROM yourTable
WHERE name = 'Jane'
ORDER BY id DESC
LIMIT 1
But because you mention autocomplete functionality you should use:
WHERE name LIKE 'Jane%'
To have the latest, you need to have a field dateAdded which stores the date you ran the insert command.
Following which, you use MAX(dateAdded) to get the latest ID (since, as you mentioned, it may decrease as well)
UPDATE:
if ID doesn't decrease, you can always use MAX(ID)
SELECT MAX(id), v from tablename where name = 'Jane'
UPDATE:
This has been tested:
SELECT ID, v from tableName where ID = (SELECT MAX(ID) as ID from tableName where name like '%Jane%')
Try the following query (h/t #lamak)
WITH CTE AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY name
ORDER BY [id] DESC)
FROM poro
)
SELECT *
FROM CTE
WHERE RN = 1

MySQL Query Order by before Group By

name order_id
tom | 1 |
tom | 0 |
tom | 2 |
tom | 3 |
tom | 4 |
ken | 2 |
ken | 1 |
ken | 0 |
I have a table like above, how can I select the data group by the name and order by the order id. I already try the query below but it's not the result I want.
SELECT * FROM tbl_dummy GROUP BY name ORDER BY order_id ASC
This might be what you want:
SELECT name, MIN(order_id) AS order_id
FROM tbl_dummy
GROUP BY name
ORDER BY order_id
SELECT * FROM tbl_dummy GROUP by name,order_id order by name,order_id
For using GROUP BY clause, you must use some type of aggregate function (SUM, MIN, MAX ..) on all the other columns that you are selecting.
Try understand it this way, if you do group by name in the above data, then you will have two rows in the result, one for tom and one for ken. But what value of order_id should it display against each name? It cannot display all the values separated by comma (or anything else like that). The value to be shown must be a value calculated using all the values corresponding to that name. It could either be sum, average, min or max of all the values.
Ref: http://dev.mysql.com/doc/refman/5.7/en/group-by-functions.html
May be what you are looking for is to order your results by name first and then order_id in increasing order. In that case you can use order by multiple columns
SELECT name, order_id from yourtable order by name, order_id;

SQL- Top count(column1) w.r.t Distinct column2

I have a table with three columns,
| User_id (INT) | CountryCode (VARCHAR) | channel_accessed (VARCHAR) |
There is no primary key over here, so repetition is possible for all columns.
I want to write a SQL query that returns Top countries name & there corresponding count w.r.t unique User_id
Tried following this Using group by on multiple columns but this has not helped me much.
sample data :
| User_id (INT) | CountryCode (VARCHAR) | channel_accessed (VARCHAR) |
1 US ARY
2 CA ARY
3 CA MTV
2 CA HUMTV
4 US Tensports
5 US Star Sports
2 CA PTV
2 CA QTV
2 CA NATGEO
Expected Result : US, because it has more unique users.
Try this:
select CountryCode
from yourtable
group by CountryCode
order by count(distinct User_id) desc
limit 1
SQLFiddle Demo
If the channel_accessed column doesn't matter then you could try
SELECT CountryCode, MAX(user_count)
FROM (SELECT CountryCode,
COUNT(DISTINCT(user_id)) as user_count
FROM table_name
GROUP BY CountryCode)

How to iterate over possible values over values of a column

I have a table, which stores names and numbers associated with it. Each of these numbers are of a certain type. The combination of name and type is unique.
name | type | number
---------------------
a | t0 | 5
a | t1 | 6
b | t0 | 7
c | t1 | 8
And I want this table as a result, which shows the numbers which are associated with that name, regardless of type accumulated.
name | sum
------------
a | 11
c | 8
b | 7
Now I know the SUM() function and I have written this so far:
SELECT name, SUM( ??SELECT name, SUM(number) WHERE name = 'a'?? ) AS sum
FROM table
ORDER BY sum DESC;
The thing is I don't know how to write the inner part of the SUM() function, as I can't use SELECT statements inside of functions. Also I don't know how I can iterate over the possible values of the name column.
SELECT NAME,
Sum(number) As 'Sum'
FROM table
GROUP BY NAME
ORDER BY Sum(number) DESC;
You need to use GROUP BY along with SUM:
SELECT name, SUM(number) AS sum
FROM tableName
GROUP BY name
ORDER BY SUM(number) DESC; -- or ORDER BY sum DESC; - it is identical

SQL: Group by - further attribute with largest quantity

I'm new to SQL and facing following problem:
This is my table:
name city people
-----|-----|--------|
John | A | 5 |
Ben | D | 6 |
John | A | 5 |
Ben | A | 5 |
John | B | 8 |
Ben | D | 6 |
I want to group by the name and receive associated to the name that city with the largest quantity. As a second query, instead of the largest quantity, that city with the highest sum of inhabitants.
This would be the outcome for the first query:
name city
-----|-----|
John | A |
Ben | D |
Thank you!
I don't know exactly what you mean by "to the name that city with the largest quantity". What I understood was you sum the column 'people' per couple (name, city), thus (John, A) would be 10 and (John, B) would be 8, and you take the max value to get (John, A).
In this case, you can do it this way:
SELECT
name,
city
FROM
(SELECT
name,
city,
SUM(people) AS tot
FROM table
GROUP BY name, city
ORDER BY name ASC, tot DESC) AS a
GROUP BY name ;
As for the city with the largest number of inhabitants, you just have to group by city and sum the column people and take the max:
SELECT
city,
SUM(people) AS nb_inhabitants
FROM table
GROUP BY city
ORDER BY nb_inhabitants DESC
LIMIT 1;
SELECT name, city, sum( people )
FROM `detail`
GROUP BY name
ORDER BY people ASC
LIMIT 0 , 30
I am not really understand what your are expecting ,but I guess you want to do this thing.
Description : I am group by people from there name , and got sum of the people and make them ASC order. I am not sure your are expect this thing.
You can also , group people by their city
SELECT name, city, sum( people )
FROM `detail`
GROUP BY city
ORDER BY people ASC
LIMIT 0 , 30
If this not you expect , Please , further describe question ,we will try to give some answer.
Try this, I have tried by making a table as per your sample data,
CREATE TABLE KaiTable
(
NAME VARCHAR(50)
,city CHAR(1)
,people INT
);
INSERT INTO KaiTable
VALUES
(
'John'
,'A'
,5
),
('Ben ' ,'D' ,6),
('John' ,'A' ,5),
('Ben ' ,'A' ,5) ,
('John' ,'B' ,8) ,
('Ben ' ,'D' ,6)
SELECT NAME,city
FROM
(SELECT NAME,city,SUM(people) AS PeopleSum
FROM KaiTable
GROUP BY NAME, city
ORDER BY NAME ASC, PeopleSum DESC) AS a
GROUP BY NAME DESC;
SQL Fiddle Demo