I am a beginner at SQL and I am trying to solve this question from HackerRank using Subquery. Could you tell me what I did wrong?
Problem
Query the two cities in STATION with the shortest and longest CITY names, as well as their respective lengths (i.e.: number of characters in the name). If there is more than one smallest or largest city, choose the one that comes first when ordered alphabetically.
For example, CITY has four entries: DEF, ABC, PQRS and WXY.
Sample output
ABC 3
PQRS 4
Explanation
When ordered alphabetically, the CITY names are listed as ABC, DEF, PQRS, and WXY, with lengths and . The longest name is PQRS, but there are options for shortest named city. Choose ABC, because it comes first alphabetically.
My Solution
SELECT
CITY,
LENGTH(SELECT MAX(CITY)
FROM STATION) AS Length
FROM STATION
ROWNUM 1;
SELECT
CITY, LENGTH(SELECT MIN(CITY)
FROM STATION) AS Length
FROM STATION
ROWNUM 1;
You can UNION the first and the last
CREATE tABLE A (city varchar(10))
INSERT INTO A VALUES ('DEF'),('ABC'), ('PQRS'), ('WXY')
(SELECT city
, LENGTH(city)
FROM A
ORDER BY LENGTH(city) ASC,city LIMIT 1)
UNION ALL
(SELECT city
, LENGTH(city)
FROM A
ORDER BY LENGTH(city) DESC,city LIMIT 1)
city | LENGTH(city)
:--- | -----------:
ABC | 3
PQRS | 4
db<>fiddle here
My solution without using UNION:
select city,length(city) from station order by length(city),city limit 1;
select city,length(city) from station order by length(city) desc ,city limit 1;
Related
select min(length(city)), city
from station
group by min(length(city));
select max(length(city)), city
from station
group by min(length(city));
output = ERROR 1056 (42000) at line 1: Can't group on 'min(length(city))'
I am trying to get minimum and maximum char length with city name. I thought this algorithm will be okay.
Why ı can't group on min(length(city))
It doesn't make sense to group by an aggregate function. Aggregate functions are called after grouping, to calculate something for all the rows in the group (such as a sum total).
You can use a subquery to calculate an aggregate for the entire table. Then you can compare this with individual rows.
SELECT city, LENGTH(city) AS length
FROM station
WHERE LENGTH(city) = (SELECT MIN(length(city)) FROM station);
Another solution :
SELECT CITY , LENGTH(city) AS length
FROM STATION
WHERE LENGTH(CITY)
IN (
SELECT MAX(LENGTH(CITY))
FROM STATION
UNION
SELECT MIN(LENGTH(CITY))
FROM STATION )
In task below
Hackerrank
i did that query
SELECT CITY ,length(CITY ) from STATION where length(CITY )in(
select max(length(CITY ))from STATION union select min(length(CITY ))from STATION )Group by length(CITY )
order by length(CITY ) desc,CITY ;
i recieved Error
also i make another query like that
Select max(length(CITY)),CITY from STATION Group by length(CITY) Order by length(CITY)Desc;
and recieved that error
Error
The question phrases as:
Query the two cities in STATION with the shortest and longest CITY names, as well as their respective lengths (i.e.: number of characters in the name). If there is more than one smallest or largest city, choose the one that comes first when ordered alphabetically.
You don't really need aggregation to achieve this task.
I think this would be simpler expressed with union all and two row-limiting queries (one that sorts cities by ascending length, the other by descending length):
(
select city, char_length(city) cnt_chars
from station
order by char_length(city), city limit 1
) union all (
select city, char_length(city)
from station
order by char_length(city) desc, city limit 1
)
If there is only one city in the table (or if all cities have the same length), then union might be more appropriate than union all (so the same city does not appear twice in the resultset).
Alternatively, if you are running MySQL 8.0, you can use window functions:
select city, cnt_chars
from (
select s.*,
row_number() over(order by char_length(city), city) rn_asc,
row_number() over(order by char_length(city) desc, city) rn_desc
from station s
) s
where 1 in (rn_asc, rn_desc)
Side note: char_length() is safer than length(). The former counts characters, while the latter counts bytes (if your strings have multi-byte characters, this is not what you want).
You are trying to select CITY name and length(CITY) but grouping only by length(CITY). In case when two or more cities have the some value for length(CITY) mysql does not know which of the CITY should be selected.
My code is this but gives error, don't know why. Please help!
select city,
min(length(city))
from station
group by length(city)=min(length(city))
order by city asc;
If you just want the city with the shortest name, you can simply order by and limit:
select city, char_length(city) city_length
from station
order by city_length
limit 1
This returns just one row. On the other hand, if you want to allow bottom ties, then you can filter with a subquery, like so:
select city, char_length(city) city_length
from station
where char_length(city) = (select min(char_length(city)) from station)
I'm new to mysql and I have two correctly working select statements with longest and shortest names. I can't really understand how can I join them in one statement. Can someone help, please.
Here are the queries:
SELECT name AS Country, CHAR_LENGTH(name) AS NameLength
FROM country
ORDER BY CHAR_LENGTH(name) DESC, name
LIMIT 1;
SELECT name AS Country, CHAR_LENGTH(name) AS NameLength
FROM country
ORDER BY CHAR_LENGTH(name), name
LIMIT 1;
The result I'm looking for is:
Country NameLength
----------------------------------------------------------
South Georgia and the South Sandwich Islands 44
Chad 4
Cuba 4
You use UNION:
SELECT Country, NameLength FROM (
SELECT name AS Country, CHAR_LENGTH(name) AS NameLength FROM country LIMIT 1;
UNION
SELECT name AS Country, CHAR_LENGTH(name) AS NameLength FROM country LIMIT 1; )a
ORDER BY NameLength DESC, Country
Query the two cities in STATION with the shortest and longest CITY names, as well as their respective lengths (i.e.: number of characters in the name). If there is more than one smallest or largest city, choose the one that comes first when ordered alphabetically.
SELECT CITY,CHAR_LENGTH(CITY) AS CHARLENGTH
FROM STATION
ORDER BY CHARLENGTH ASC
LIMIT 1;
SELECT CITY,CHAR_LENGTH(CITY) AS CHARLENGTH
FROM STATION
ORDER BY CHARLENGTH DESC
LIMIT 1;
Something like this?
##DROP TABLE STATION;
CREATE TABLE STATION (CITY VARCHAR(100));
INSERT INTO STATION VALUES ('aaaaaaa');
INSERT INTO STATION VALUES ('bbbbbbb');
INSERT INTO STATION VALUES ('cccc');
INSERT INTO STATION VALUES ('dd');
SELECT *
FROM
(SELECT CITY,CHAR_LENGTH(CITY) AS CHARLENGTH FROM STATION ORDER BY CHARLENGTH ASC, CITY LIMIT 1) A
UNION ALL
SELECT * FROM
(SELECT CITY,CHAR_LENGTH(CITY) AS CHARLENGTH FROM STATION ORDER BY CHARLENGTH DESC, CITY LIMIT 1) B
Output:
CITY CHARLENGTH
1 dd 2
2 aaaaaaa 7