使用 EXCEPT SQLite 命令删除除一行以外的所有行
Remove all the rows except one with the EXCEPT SQLite command
从一个数据集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;
当我尝试从 A
中删除 B 时
A EXCEPT B
我希望保留第一个最短的名字,但它没有出现。
我会在这里使用 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);
当您在 B 查询中设置 OFFSET 2
时,您不会得到:
除第一个字母以外的所有最短名字
相反,你得到:
所有最短的名字,除了 前 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
子句(以及 LIMIT
和 OFFSET
)仅适用于您的 B 查询,但是这不是它的解释方式。
实际上 ORDER BY
(以及 LIMIT
和 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
)
从一个数据集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;
当我尝试从 A
中删除 B 时A EXCEPT B
我希望保留第一个最短的名字,但它没有出现。
我会在这里使用 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);
当您在 B 查询中设置 OFFSET 2
时,您不会得到:
除第一个字母以外的所有最短名字
相反,你得到:
所有最短的名字,除了 前 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
子句(以及 LIMIT
和 OFFSET
)仅适用于您的 B 查询,但是这不是它的解释方式。
实际上 ORDER BY
(以及 LIMIT
和 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
)