Сначала отсортировать результат с пустыми строками

У меня есть эта locations таблица:

+----+-----------+------------+----------+
| id |  country  |   state    |   city   |
+----+-----------+------------+----------+
|  1 |  US       | Georgia    |  Atlanta |
|  2 |  US       | California |          |
|  3 |  US       |            |          |
|  4 |  Canada   |  Ontario   |          |
|  5 |  Canada   |  Manitoba  | Winnipeg |
|  6 |  Canada   |            |          |

Я хочу создать запрос, но не смог правильно построить свой ORDER BY. Это результат, который я хочу:

+----+-----------+------------+----------+
| id |  country  |   state    |   city   |
+----+-----------+------------+----------+
|  6 |  Canada   |            |          |
|  3 |  US       |            |          |
|  4 |  Canada   | Ontario    |          |
|  2 |  US       | California |          |
|  5 |  Canada   | Manitoba   | Winnipeg |
|  1 |  US       | Georgia    | Atlanta  |

По сути, это приоритет, которому я хочу следовать:

  1. Список стран. Алфавитный порядок.
  2. Государственный листинг. Алфавитный порядок.
  3. Листинг города. Алфавитный порядок.

Этот запрос, похоже, не учитывает пустые столбцы (я не использую NULL в своей таблице locations):

SELECT * FROM locations
ORDER BY 
    country,state,city  

Это больше похоже на чередующийся порядок

Strawberry 11.07.2019 12:41

Считаете ли вы, что такие операции сильно нагружают процессор? Я подумываю о предварительном заказе столика.

user1506104 11.07.2019 12:46

Если вам нужен этот порядок только для целей отображения (без разбиения на страницы); Я бы предпочел сделать это в коде приложения (например, PHP); В этом случае MySQL может нет может использовать индекс, тем самым нагружая ЦП.

Madhur Bhaiya 11.07.2019 12:48

@user1506104 user1506104 В SQL нет концепции предварительного заказа данных таблицы. Самое близкое к тому, что вы имеете в виду, - это создать индекс, который позволит вашей базе данных сортировать данные так, как вы хотите их видеть.

Tim Biegeleisen 11.07.2019 12:49

@MadhurBhaiya, у меня есть все места в мире, и я рисую страницы, поэтому я не отправляю каждое место в свое приложение. Я считаю, что мой лучший вариант - сделать заказ в моем запросе sql?

user1506104 11.07.2019 12:52

@TimBiegeleisen «нет концепции предварительного заказа». я узнал кое-что сегодня.

user1506104 11.07.2019 12:53

@user1506104 user1506104 Если вы разбиваете на страницы, то вам подойдет SQL-запрос. Если данные в этой таблице не являются динамическими (вообще не должны быть, если вы уже учли все места в мире), то вы можете заново заполнить эту таблицу в нужном вам порядке. А затем используйте ключ автоинкремента для получения данных. В противном случае этот конкретный тип сложной сортировки не сможет использовать какой-либо индекс.

Madhur Bhaiya 11.07.2019 12:58
«Если вы разбиваете на страницы, то SQL-запрос — это путь» @MadhurBhaiya зависит от того, как написан SQL, и от количества записей в таблице. Большинство будет использовать LIMIT 1000000, 1000, поскольку это кажется наиболее естественным в MySQL для разбиения на страницы, но это ужасно для производительности, поскольку базам данных MySQL необходимо получить 1001000 записей. ..
Raymond Nijland 11.07.2019 13:10

@RaymondNijland да; Каков обходной путь в этом случае? Хотя в большинстве практических приложений ни один пользователь не перейдет на 1000-ю страницу... если этот пользователь не попытается копнуть намного глубже...

Madhur Bhaiya 11.07.2019 13:21
«Каков обходной путь в этом случае? Хотя в большинстве практических приложений ни один пользователь не перейдет на 1000-ю страницу… если этот пользователь не попытается копнуть намного глубже…» Поисковые системы могут и будут заходить так глубоко. @MadhurBhaiya общий подход заключается в использовании столбца PRIMARY KEY и auto_increment, использовании ORDER BY в столбце, а также в то время как для сохранения результатов на 100% детерминированных (фиксированных) и отслеживания id в приложении.. более-менее похоже WHERE id >= 1000000 ORDER BY id LIMIT 1000
Raymond Nijland 11.07.2019 14:24

@RaymondNijland Я начал использовать аналогичный подход когда-то назад ... хотя он не работает во всех случаях ... спасибо за совет!

Madhur Bhaiya 11.07.2019 14:26
"не работает во всех случаях, хотя.." @MadhurBhaiya также можно развернуть оконную функцию в MySQL 8, чтобы ранжировать/упорядочить (с RANK()/ROW_NUMBER()) набор результатов и «ограничить» (фильтровать) его. Или смоделируйте его с помощью пользовательских переменных MySQL в более низких версиях. Это должно расширить возможные пользовательские случаи по сравнению с другим методом. Фактически использование оконной функции для «ограничения» наборов результатов было одним из единственно допустимых стандартных решений ANSI/ISO SQL до тех пор, пока SQL 2016 определил FETCH ограничение наборов результатов или доставленных таблиц.
Raymond Nijland 11.07.2019 14:38
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
1
12
67
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Попробуйте это ORDER BY предложение:

SELECT *
FROM locations
ORDER BY
    CASE WHEN state = '' AND city = '' THEN 0
         WHEN city = '' THEN 1
         ELSE 2 END,
    country,
    state,
    city;

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

Для версий до 8.0...

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,country VARCHAR(20) NOT NULL
,state VARCHAR(20) NULL
,city VARCHAR(20) NULL
);

INSERT INTO my_table VALUES
(1,'US','Georgia','Atlanta'),
(2,'US','California',NULL),
(3,'US',NULL,NULL),
(4,'Canada','Ontario',NULL),
(5,'Canada','Manitoba','Winnipeg'),
(6,'Canada',NULL,NULL);

SELECT id
     , country
     , state
     , city 
  FROM 
     ( SELECT x.*
            , CASE WHEN @prev=country THEN @i:=@i+1 ELSE @i:=1 END i
            , @prev:=country 
         FROM my_table x
            , (SELECT @prev:=null,@i:=0) vars 
        ORDER 
           BY country
            , city
            , state
     ) a 
 ORDER 
    BY i
     , country;
+----+---------+------------+----------+
| id | country | state      | city     |
+----+---------+------------+----------+
|  6 | Canada  | NULL       | NULL     |
|  3 | US      | NULL       | NULL     |
|  4 | Canada  | Ontario    | NULL     |
|  2 | US      | California | NULL     |
|  5 | Canada  | Manitoba   | Winnipeg |
|  1 | US      | Georgia    | Atlanta  |
+----+---------+------------+----------+

Спасибо за попытку. я попробую это позже (поскольку у меня уже есть принятый ответ). если это сработает, я могу вместо этого дать вам награду.

user1506104 11.07.2019 13:04
select *
from locations
order by 
  state <> '',
  city  <> '',
  country,
  state,
  city

db-рабочий пример

Обратите внимание, что в MySQL логическое выражение возвращает 0 (для FALSE) или 1 (для TRUE). Это означает, что для пустой строки statestate <> '' вернет 0 и, таким образом, упорядочится первым.

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