SQL-запрос для поиска самого длинного имени и самого короткого имени в таблице

У меня есть таблица с одним из столбцов типа varchar(город). и хотите найти самые длинные и короткие значения, хранящиеся в этом столбце.

select a.city, a.city_length from (select city, char_length(city) city_length 
from station order by city, city_length) a
where a.city_length = (select min(a.city_length) from a) or
      a.city_length = (select max(a.city_length) from a)
group by a.city_length;

Кто-нибудь может помочь? Спасибо


Одно из решений:

select * from (select city, char_length(city) city_length from station order by city, city_length) a group by a.city_length order by a.city_length limit 1;
select * from (select city, char_length(city) city_length from station order by city, city_length) a group by a.city_length order by a.city_length desc limit 1;

34 ответа

Я не думаю, что нам нужно использовать функции Min и Max, а Group by также не требуется.

Мы можем достичь этого, используя следующий код:

select top 1 City, LEN(City) City_Length from STATION order by City_Length ASC,City ASC

select top 1 CITY, LEN(city) City_Length from station order by City_Length desc, City ASC

но в этом случае он отобразит вывод в 2 таблицах, и если мы хотим объединить в одну таблицу, мы можем использовать Union или Union ALL. Ниже приведен SQL-запрос для того же

  select * from (
     select top 1 City, LEN(City) City_Length from STATION order by City_Length ASC,City ASC) TblMin
   UNION
   select * from (
   select top 1 CITY, LEN(city) City_Length from STATION order by City_Length desc, City ASC) TblMax

здесь я вкладываю инструкцию select в подзапрос, потому что когда мы используем предложение order by, мы не можем использовать Union или Union ALL напрямую, поэтому я написал его в подзапросе.

Кратчайший:

select TOP 1 CITY,LEN(CITY) LengthOfCity FROM STATION ORDER BY LengthOfCity ASC, CITY ASC;

Серия:

select TOP 1 CITY,LEN(CITY) LengthOfCity FROM STATION ORDER BY LengthOfCity DESC, CITY ASC;

Это работает для проблемы вызова HackerRank (MS SQL Server).

В MySQL

(select city, LENGTH(city) cityLength  from station order by cityLength desc,city asc LIMIT 1)
    union all
    (select city, LENGTH(city) cityLength  from station order by cityLength asc,city asc LIMIT 1)

Может быть, более простой вариант, так как я полагаю, что вы ищете помощь в решении вопроса о рейтинге Хакера? Добавление лимитов облегчило мне отладку, когда проблема была с возвращенной ошибкой.

SELECT city, length(city) FROM station order by length(city) desc limit 1;

SELECT city, length(city) FROM station order by length(city) asc, city asc limit 1

Ваш запрос требует всего несколько настроек. Основная проблема заключается в том, что вы не можете использовать a в подзапросе, как вы делаете:

select a.city, a.city_length
from (select city, char_length(city) city_length 
      from station 
     ) a
where a.city_length = (select min(char_length(city)) from station) or
      a.city_length = (select max(char_length(city)) from station);

Тем не менее, более простой способ написать запрос:

select s.*
from station s cross join
     (select min(char_length(city)) as mincl, max(char_length(city)) as maxcl
      from station
     ) ss
where char_length(s.city) in (mincl, maxcl);

Это еще один способ сделать это в MySQL. Может быть, не самый лучший, но логически верный вариант.

      select
   city,
   length(city) 
from
   station 
where
   length(city) in 
   (
      select
         max(length(city)) 
      from
         station 
      union
      select
         min(length(city)) 
      from
         station
   )
order by
   length(city) desc,
   city asc limit 2;

В Oracle:

выберите * из (выберите город, мин. (длина (город)) минл из группы станций по порядку городов по минл, город) где rownum = 1;
выберите * из (выберите город, max(длина (город)) maxl из группы станций по порядку городов по maxl desc, city), где rownum = 1;

По возрастанию:

ВЫБЕРИТЕ город, CHAR_LENGTH(город) ОТ станции ЗАКАЗАТЬ CHAR_LENGTH (город), город LIMIT 1;

По убыванию:

ВЫБЕРИТЕ город, CHAR_LENGTH(город) ОТ станции ЗАКАЗАТЬ CHAR_LENGTH (город) DESC, город LIMIT 1;

Это подход с CTE. Сначала он находит самый длинный и самый короткий, чем соответствующие города:

DECLARE @tbl TABLE(CityName VARCHAR(100));
INSERT INTO @tbl VALUES ('xy'),('Long name'),('very long name'),('middle'),('extremely long name');

WITH MyCTE AS 
(
    SELECT MAX(LEN(CityName)) AS Longest
          ,MIN(LEN(CityName)) AS Shortest
    FROM @tbl
)
SELECT * 
FROM MyCTE
--You must think about the chance of more than one city matching the given length
CROSS APPLY(SELECT TOP 1 CityName FROM @tbl WHERE LEN(CityName)=Longest) AS LongestCity(LongName)
CROSS APPLY(SELECT TOP 1 CityName FROM @tbl WHERE LEN(CityName)=Shortest) AS ShortestCity(ShortName)

Результат

Longest Shortest    LongName               ShortName
19       2          extremely long name    xy

Первоначально найти самую короткую длину city и принимая союз с самой длинной длиной city, Это минимизирует сложность запроса.

(select city, char_length(city) as len_city
from station
order by len_city limit 1)
union ( select city, char_length(city) as len_city
    from station
    order by len_city desc limit 1) 
order by len_city
select top(1) city, max(len(city)) [Length] from station group by city order by [Length]
select top(1) city, max(len(city)) [Length] from station group by city order by [Length] DESC

Протестировано в SQL Server 2016

Я сделал это в SQL Server, используя функции CTE и dens_rank. Как работает рейтинг?

Первый раздел (формы групп) по длинам, то есть одинаковые длины составляют группу (раздел). Затем упорядочите все имена в алфавитном порядке в каждом разделе. Затем назначьте ранги (столбец dRank) в каждом разделе. Таким образом, ранг 1 в каждой группе будет присвоен именам, которые в алфавитном порядке появляются первыми в соответствующем разделе. Все это происходит в общем табличном выражении (блок cte)

"with cte as
(
select *, LEN(city) as length, DENSE_RANK() over (partition by len(city) order by city) as dRank from Station
)"

select city,length from cte where dRank = 1 and length = (select MIN(length) from cte)
UNION
select city,length from cte where dRank = 1 and length = (select max(length) from cte)"

Для кратчайшего названия города: ВЫБЕРИТЕ ST.CITY, ДЛИНУ (ST.CITY) КАК ДЛИНА ОТ СТАНЦИИ ST ЗАКАЗ ДЛИНОЙ ASC, ST.CITY ASC LIMIT 1;

Для самого длинного названия города: ВЫБЕРИТЕ ST.CITY, ДЛИНУ (ST.CITY) КАК ДЛИНА ОТ СТАНЦИИ ST ЗАКАЗ ПО ДЛИНЕ DESC, ST.CITY DESC LIMIT 1;

Я использовал предложение WITH для Oracle, чтобы сохранить самые короткие / самые длинные имена во временной переменной, а не выполнять запросы внутри основного предложения from.Пример предложения SQL WITH

      WITH shortnames AS
(SELECT city, length(city) 
 FROM station 
 ORDER BY length(city) asc, city),

 longnames AS
 (SELECT city, length(city) 
  FROM station
  ORDER BY length(city) desc, city)

SELECT * FROM shortnames WHERE ROWNUM=1
UNION ALL
SELECT * FROM longnames WHERE ROWNUM=1;

Этот запрос будет хорошо работать в ваших условиях, эти 2 запроса точно такие же. В первом запросе мы просто упорядочиваем запись в порядке убывания, чтобы взять название города с наибольшей длиной, а во второй части мы просто записываем записи в порядке возрастания, чтобы взять город с минимальной длиной, все остальные запросы одинаковы. Кидни, погляди.

Деталь:

  1. Выберите заявление, чтобы вынуть записи
  2. Используйте group by, потому что я использую функцию агрегирования Len().
  3. Упорядочивание всех найденных записей в порядке убывания и возрастания, чтобы получить верхнюю 1 и взять максимальную и минимальную длину города.

    select  Top 1  City,max(len(City)) as Length  
    from STATION 
    group by City 
    ORDER BY Length desc 
    
    select  Top 1  City,max(len(City)) as Length  
    from STATION 
    group by City 
    ORDER BY Length ASC
    

В дополнение ко всем ответам выше, я хочу поделиться трюком, который я использовал в T-SQL, но он существует в любой версии:

  1. Я вычисляю длину с ведущими 0 колодками, которые позволяют сортировать по алфавиту
    • В этом примере я предполагаю, что весь текст будет меньше 10 МБ, поэтому максимум 7-значное число
    • REPLACE(STR(CAST(LEN(city) AS INT) ,7), SPACE(1), '0')
  2. Я добавляю 0-дополненныйLEN()к стоимости
    • concat( <step1> , city )
  3. я выбираюMAX()илиMIN()
    • Это работает, потому что число, дополненное 0, может быть отсортировано в алфавитном порядке.
    • Пример:"099" < "100", но"99" > "100"потому что"9" > "1"в ascii)
  4. Я удаляю число из значения
    • STUFF( <step 3> ,1,7,'')поскольку мы заменяем 7 первых символов на '', и наш номер всегда будет состоять из 7 символов из-за заполнения 0

Наконец, следующий SQL вернет оба ответа в одном запросе, без окон и без объединений:

      SELECT
    STUFF(min(
        concat(
            REPLACE(STR(CAST(LEN(city) AS INT) ,7), SPACE(1), '0')
            ,city)) 
        ,1,7,'')
        as [min_len],
    STUFF(max(
        concat(
            REPLACE(STR(CAST(LEN(city) AS INT) ,7), SPACE(1), '0')
            ,city)) 
        ,1,7,'')
        as [max_len]
from station

Это также позволяет вам получить минимальную максимальную информацию из любого другого столбца (в той же строке), например столбца «station_ranking», если он существует.

Вот пример dbfiddle с MySQL:

      SELECT
    SUBSTR(min(
        concat(
            LPAD(length(city), 7, '0') 
            ,city)) 
        ,7+1)
        as min_name_len,
    SUBSTR(max(
        concat(
            LPAD(station_rank, 2, '0') 
            ,city)) 
        ,2+1)
        as max_name_rank
from stations

https://www.db-fiddle.com/f/76ew1fK9D5V3vopbGUuYxh/4

Следующий запрос кажется достаточно простым:

select 
    city, leng 
from
    (select top 1 
         city, len(city) leng 
     from 
         station 
     where 
         len(city) = (select min(len(city)) from station) 
     order by 
         city

     Union all

     select top 1 
         city, len(city) leng 
     from 
         station 
     where 
         len(city) = (select max(len(city)) from station)  
     order by 
         city) result;

1-й запрос внутри возвращает город с минимальной длиной, а 2-й запрос возвращает город с максимальной длиной.

Надеюсь это поможет.

Это работает для mysql

      -- smallest
SELECT city, length(city) FROM station 
WHERE length(city) = (select min(length(city)) from station)
ORDER BY city
limit 1;

-- largest
SELECT city, length(city) FROM station 
WHERE length(city) = (select max(length(city)) from station)
ORDER BY city
limit 1;

В Oracle это было бы,

SELECT CITY,LENGTH(CITY) FROM   (SELECT MIN(CITY) CITY  FROM STATION WHERE LENGTH(CITY)=(SELECT MIN(LENGTH(CITY)) FROM STATION))
UNION ALL
SELECT CITY,LENGTH(CITY) FROM   (SELECT MAX(CITY) CITY  FROM STATION WHERE LENGTH(CITY)=(SELECT MAX(LENGTH(CITY)) FROM STATION));    

Для оракула:

select min(city),length(city) from station where length(city) <= all(select 
length(city) from station) group by length(city);

select max(city),length(city) from station where length(city) >= all(select 
length(city) from station) group by length(city);

В Oracle 12c это можно сделать с помощью FETCH..FIRST

самый короткий

select * FROM station ORDER BY LENGTH(city) DESC FETCH FIRST 1 ROWS ONLY;

самыйдлинный

select * FROM station ORDER BY LENGTH(city) ASC FETCH FIRST 1 ROWS ONLY;

Выберите город, длина (город) из (выберите город, длина (город), ранг () над (разделение по длине (город), порядок по длине (город), город по возрастанию) как rnk от станции) a, где a.rnk=1;

В Oracle мы можем сделать вот так

select city, length(city)
from (select city from STATION order by length(city) DESC, city ASC)
where rownum = 1 
union
select city, length(city)  
from (select city from STATION order by length(city), city ASC)
where rownum = 1;

Идея состоит в том, чтобы получить самый длинный и самый короткий город, а затем объединить их в один результат.

SELECT MAX(LENGTH(transaction_id)) AS Longest ,MIN(LENGTH(transaction_id)) AS Shortest FROM cards

Для Oracle SQL в одной результирующей таблице. Это позволит получить минимальное и максимальное названия городов, и, если они имеют одинаковую длину, первый город будет отсортирован в алфавитном порядке.

SELECT * FROM (
    SELECT CITY, LENGTH(CITY) CITY_LENGTH 
    FROM STATION 
    ORDER BY CITY_LENGTH ASC, CITY ASC ) MAX_LEN  
WHERE ROWNUM <= 1
UNION
SELECT * FROM (
    SELECT CITY, LENGTH(CITY) CITY_LENGTH 
    FROM STATION 
    ORDER BY  CITY_LENGTH DESC, CITY ASC ) MIN_LENGTH  
WHERE ROWNUM <= 1;

В Oracle (и любом другом языке, который поддерживает аналитические функции), используя ROW_NUMBER Аналитическая функция позволяет назначать строки уникальный номер в соответствии с ASC окончание (или DESC окончание) длина города. Поскольку может быть несколько строк одинаковой длины, можно применить вторичный порядок, чтобы получить первый город этой длины в алфавитном порядке. Тогда все, что вам нужно, это внешний запрос, чтобы отфильтровать результаты только по самому короткому (или самому длинному) имени:

SELECT city
FROM   (
  SELECT CITY,
         ROW_NUMBER() OVER ( ORDER BY LENGTH( CITY ) ASC,  CITY ) shortest_rn,
         ROW_NUMBER() OVER ( ORDER BY LENGTH( CITY ) DESC, CITY ) longest_rn
  FROM   station
)
WHERE shortest_rn = 1
OR    longest_rn  = 1;

Если вы хотите вернуть все города с самым коротким (или самым длинным) названием, используйте DENSE_RANK вместо ROW_NUMBER:

SELECT city
FROM   (
  SELECT CITY,
         DENSE_RANK() OVER ( ORDER BY LENGTH( CITY ) ASC  ) shortest_rn,
         DENSE_RANK() OVER ( ORDER BY LENGTH( CITY ) DESC ) longest_rn
  FROM   station
)
WHERE shortest_rn = 1
OR    longest_rn  = 1
ORDER BY shortest_rn, city; -- Shortest first and order tied lengths alphabetically

Length (CITY) вернет длину строки,

https://www.w3schools.com/sql/func_mysql_length.asp

(select CITY, length(CITY) from STATION order by length(CITY),CITY limit 1)
UNION
(select CITY, length(CITY) from STATION order by length(CITY) DESC limit 1);

Для Oracle это сработало для меня (HackerRank)

      --shortest 
SELECT CITY,L FROM 
(select CITY,length(CITY) L
from STATION   
order by length(CITY) ASC, CITY ASC)
WHERE ROWNUM=1
UNION ALL 
--longest 
SELECT CITY,L FROM 
(select CITY,length(CITY) L
from STATION   
order by length(CITY) DESC, CITY ASC)
WHERE ROWNUM=1;

Texto original Я пробовал много способов, но эту работу я упорядочил по длине, а затем в алфавитном порядке, и в итоге получил только первую строку.

Вот решение, которое строго использует MIN и MAX

Концепция здесь заключается в применении к длине названия города. В пределах этих результатов снова применить MINк самому названию города , чтобы найти первый по алфавиту.

Конечно, используйте MAXтаким же образом найти максимальную длину города и выполнить UNIONиз двух запросов для окончательного решения.

Никаких сортов, ASC, DESC, LIMIT, или же ORDER BYнужный.

Отличная ссылка:https://www.zentut.com/sql-tutorial/sql-min-max/

      (
    SELECT s3.CITY, s3.Len 
    FROM (
        SELECT CITY, s1.Len
        FROM (
            SELECT CITY, LENGTH(CITY) AS Len
            FROM STATION
        ) s1
        WHERE
            s1.Len = (
                SELECT MIN(s2.Len2)
                FROM (
                    SELECT LENGTH(CITY) AS Len2
                    FROM STATION
                ) s2
            )
        ) s3
    WHERE
        s3.CITY = (
            SELECT MIN(CITY)
            FROM STATION
            WHERE s3.Len = LENGTH(CITY)
        )
) UNION (
    SELECT s3.CITY, s3.Len 
    FROM (
        SELECT CITY, s1.Len
        FROM (
            SELECT CITY, LENGTH(CITY) AS Len
            FROM STATION
        ) s1
        WHERE
            s1.Len = (
                SELECT MAX(s2.Len2)
                FROM (
                    SELECT LENGTH(CITY) AS Len2
                    FROM STATION
                ) s2
            )
        ) s3
    WHERE
        s3.CITY = (
            SELECT MIN(CITY)
            FROM STATION
            WHERE s3.Len = LENGTH(CITY)
        )
);

Для базы данных Oracle:

выберите город, протяженность (город) из (выберите * из порядка станций по длине (город), город), где rownum=1

СОЮЗ

выберите город, длину (город) из (выберите * из порядка станций по длине (город) desc, city), где rownum=1;

Другие вопросы по тегам