UNION 与 CTE 一起工作,但不是没有?
UNION works with CTE, but not without?
我正在使用 PostgreSQL 11.12。
我有这个问题:
select first_name, length(first_name)
from db_employee
where length(first_name) =
(select max(length(first_name)) from db_employee)
order by 1
limit 1
union
select first_name, length(first_name)
from db_employee
where length(first_name) =
(select min(length(first_name)) from db_employee)
order by 1
limit 1
当我 运行 它时,我得到这个错误:
syntax error at or near "union"
如果我使用 CTE,它会起作用:
with cte1 as
(select first_name, length(first_name)
from db_employee
where length(first_name) =
(select max(length(first_name)) from db_employee)
order by 1
limit 1),
cte2 as
(select first_name, length(first_name)
from db_employee
where length(first_name) =
(select min(length(first_name)) from db_employee)
order by 1
limit 1)
select * from cte1
union
select * from cte2;
为什么第一个查询会导致语法错误?是否可以在不使用 CTE 的情况下让它工作?
要在 UNION
查询中包含每个 SELECT
的 LIMIT
子句,您必须添加 括号 。喜欢:
( -- !
SELECT first_name, length(first_name)
FROM db_employee
WHERE length(first_name) = (SELECT max(length(first_name)) FROM db_employee)
ORDER BY 1
LIMIT 1
) -- !
UNION
( -- !
SELECT first_name, length(first_name)
FROM db_employee
WHERE length(first_name) = (SELECT min(length(first_name)) FROM db_employee)
ORDER BY 1
LIMIT 1
) -- !
相关:
也就是说,您的查询可以优化。改用:
(
SELECT first_name, length(first_name)
FROM db_employee
ORDER BY length(first_name) DESC NULLS LAST, first_name
LIMIT 1
)
UNION ALL -- my guess
(
SELECT first_name, length(first_name)
FROM db_employee
ORDER BY length(first_name), first_name
LIMIT 1
);
细微差别:这不会完全排除具有 first_name IS NULL
的行,但仅当所有行都具有 first_name IS NULL
.
时才会显示
关于NULLS LAST
:
- Sort by column ASC, but NULL values first?
只需将 sql 部分放在单独的括号中,并在外面保留并集。
(select first_name, length(first_name)
from db_employee
where length(first_name) =
(select max(length(first_name)) from db_employee)
order by 1
limit 1)
union
(select first_name, length(first_name)
from db_employee
where length(first_name) =
(select min(length(first_name)) from db_employee)
order by 1
limit 1);
做同样事情的另一种方法:
select * from (
select first_name, l_fname
,row_number() over (order by l_fname) rn_min
,row_number() over (order by l_fname desc) rn_max
from(
select first_name,length(first_name) l_fname from db_employee
) A
) b where (rn_min = 1 or rn_max = 1);
我正在使用 PostgreSQL 11.12。
我有这个问题:
select first_name, length(first_name)
from db_employee
where length(first_name) =
(select max(length(first_name)) from db_employee)
order by 1
limit 1
union
select first_name, length(first_name)
from db_employee
where length(first_name) =
(select min(length(first_name)) from db_employee)
order by 1
limit 1
当我 运行 它时,我得到这个错误:
syntax error at or near "union"
如果我使用 CTE,它会起作用:
with cte1 as
(select first_name, length(first_name)
from db_employee
where length(first_name) =
(select max(length(first_name)) from db_employee)
order by 1
limit 1),
cte2 as
(select first_name, length(first_name)
from db_employee
where length(first_name) =
(select min(length(first_name)) from db_employee)
order by 1
limit 1)
select * from cte1
union
select * from cte2;
为什么第一个查询会导致语法错误?是否可以在不使用 CTE 的情况下让它工作?
要在 UNION
查询中包含每个 SELECT
的 LIMIT
子句,您必须添加 括号 。喜欢:
( -- !
SELECT first_name, length(first_name)
FROM db_employee
WHERE length(first_name) = (SELECT max(length(first_name)) FROM db_employee)
ORDER BY 1
LIMIT 1
) -- !
UNION
( -- !
SELECT first_name, length(first_name)
FROM db_employee
WHERE length(first_name) = (SELECT min(length(first_name)) FROM db_employee)
ORDER BY 1
LIMIT 1
) -- !
相关:
也就是说,您的查询可以优化。改用:
(
SELECT first_name, length(first_name)
FROM db_employee
ORDER BY length(first_name) DESC NULLS LAST, first_name
LIMIT 1
)
UNION ALL -- my guess
(
SELECT first_name, length(first_name)
FROM db_employee
ORDER BY length(first_name), first_name
LIMIT 1
);
细微差别:这不会完全排除具有 first_name IS NULL
的行,但仅当所有行都具有 first_name IS NULL
.
关于NULLS LAST
:
- Sort by column ASC, but NULL values first?
只需将 sql 部分放在单独的括号中,并在外面保留并集。
(select first_name, length(first_name)
from db_employee
where length(first_name) =
(select max(length(first_name)) from db_employee)
order by 1
limit 1)
union
(select first_name, length(first_name)
from db_employee
where length(first_name) =
(select min(length(first_name)) from db_employee)
order by 1
limit 1);
做同样事情的另一种方法:
select * from (
select first_name, l_fname
,row_number() over (order by l_fname) rn_min
,row_number() over (order by l_fname desc) rn_max
from(
select first_name,length(first_name) l_fname from db_employee
) A
) b where (rn_min = 1 or rn_max = 1);