使用EXCEPT SQLite命令删除所有行,除了其中一行

时间:2020-01-05 03:18:17

标签: sqlite except

从具有名称列的数据集字符中,我要查询两个名称中最短和最长的名称,以及它们各自的长度以及最小或多于一个的名称。最大的名字,我选择按字母顺序排列的第一个。

通过该查询,我得到了所有最短和最长的名称( 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;

当我尝试从 A

中删除 B
A EXCEPT B

我希望保留最短的名字,但不会出现。

2 个答案:

答案 0 :(得分:1)

我会在这里使用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);

答案 1 :(得分:0)

B 查询中设置OFFSET 2时,不会得到:
除按字母顺序排列的前1 以外的所有最短名称
相反,您得到:
除按字母顺序排列的前2 以外的所有最短名称
因为这就是OFFSET 2的作用:跳过前两行。

代码的另一个问题是 B 查询中的ORDER BY子句。
如果您有这样的话:

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子句(以及LIMITOFFSET)仅适用于您的 B 查询,但是事实并非如此。解释。
实际上,在返回行之后,将ORDER BY(以及LIMITOFFSET)应用于整个查询

要使用与您的代码相似的代码来获得所需的结果,您必须使用子查询来包装您的 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
)
相关问题