Удалите все строки, кроме одной, с помощью команды EXCEPT SQLite.

Из набора данных character, в котором есть столбец имени, я хочу запросить два имени с самыми короткими и самыми длинными именами, а также их соответствующие длины, и когда существует более одного наименьшего или самого большого имени, Я выбираю тот, который идет первым в алфавитном порядке.

С помощью этого запроса я получаю все самые короткие и самые длинные имена (A)

SELECT 
    name, LENGTH(name) AS LEN 
FROM 
    character 
WHERE 
    length(name) = (SELECT MAX(LENGTH(name)) FROM character) 
    OR length(name) = (SELECT MIN(LENGTH(name)) FROM character) 

С этим я получаю все самые короткие имена, кроме первого в алфавитном порядке (B).

SELECT 
    name, LENGTH(name) AS LEN 
FROM 
    character 
WHERE 
    length(name) = (SELECT MIN(LENGTH(name)) FROM character) 
ORDER BY 
    name DESC
LIMIT 10 OFFSET 2;

Когда я пытаюсь удалить B из A

A EXCEPT B

Я бы ожидал сохранить первое кратчайшее имя, но оно не появляется.


person nour etienne huens    schedule 05.01.2020    source источник


Ответы (2)


Когда вы устанавливаете OFFSET 2 в запросе B, вы не получаете:
все самые короткие имена, кроме первого 1 в алфавитном порядке
Вместо этого вы получаете:
все самые короткие имена, кроме первых двух в алфавитном порядке,
потому что это то, что OFFSET 2 делает: это < strong>пропускает первые две строки.

Еще одна проблема с вашим кодом – это предложение ORDER BY в запросе B.
Если у вас есть это :

SELECT name,LENGTH(name) AS LEN FROM character 
WHERE length(name) = (select max( LENGTH(name)) from character ) 
or length(name) = (select min( LENGTH(name)) from character) 
EXCEPT
SELECT name,LENGTH(name) AS LEN FROM character 
WHERE length(name) = (select min( LENGTH(name)) from character) 
ORDER BY name desc LIMIT 10 OFFSET 2;

вы можете подумать, что предложение ORDER BY (а также LIMIT и OFFSET) применяется только к вашему запросу B, но это не так.
На самом деле ORDER BYLIMIT и OFFSET) применяется ко всему запросу после возврата строк.

Чтобы получить нужные результаты с помощью кода, похожего на ваш, вы должны использовать подзапрос для переноса вашего B запрос, например:

SELECT name,LENGTH(name) AS LEN FROM character 
WHERE length(name) = (select max( LENGTH(name)) from character ) 
or length(name) = (select min( LENGTH(name)) from character) 
EXCEPT
SELECT * FROM (
  SELECT name,LENGTH(name) AS LEN FROM character 
  WHERE length(name) = (select min( LENGTH(name)) from character) 
  ORDER BY name desc LIMIT 10 OFFSET 1
)
person forpas    schedule 05.01.2020

Я бы использовал ROW_NUMBER здесь:

WITH cte AS (
    SELECT *, ROW_NUMBER() OVER (ORDER BY LENGTH(name), name) rn_min,
              ROW_NUMBER() OVER (ORDER BY LENGTH(name) DESC, name) rn_max
    FROM character
)

SELECT name, LENGTH(name) AS LEN
FROM cte
WHERE 1 IN (rn_min, rn_max)
ORDER BY LENGTH(name);
person Tim Biegeleisen    schedule 05.01.2020