SQL-是否可以从“ SELECT”子句中排除列?

时间:2019-02-11 10:48:36

标签: sql sql-server tsql

每次在子查询中执行许多复杂的处理和许多列 SELECT 时,都会遇到此问题,但最终只需要显示很少的内容即可。 无论如何,SQL(Oracle或Microsoft或其他公司)是否正在考虑使用(extra)子句以忽略不需要的列。

;with t as (
   select col1, col2, col3, col4, col5, col6, col7, col8, col9, col10
   from orders_tbl
   where order_date > getdate() -- ex. T-sql
)
, s as (
select t.*, row_number() over(partition by col1 order by col8 DESC, col9) rn
from t
)
--
-- The problem is here: if i don't explicitly select the individual columns of "t" ,then it'll display the column "rn" as well which is not required.
-- 
   select col1, col2, col3, col4, col5, col6, col7, col8, col9, col10
   from s where rn = 1
   order by col1, col2

现在,想象这样的事情-

with t as (
   select col1, col2, col3, col4, col5, col6, col7, col8, col9, col10
   from orders_tbl
   where order_date > getdate() -- ex. T-sql
)
, s as (
   select t.*, row_number() over(partition by col1 order by col8 DESC, col9) rn
from t
)
--
-- Note: the imaginary clause "exclude"
-- 
select *
from s exclude (rn) where rn = 1
order by col1, col2

请问您的想法?

2 个答案:

答案 0 :(得分:4)

如果MS Sql Server支持Google BigQuery之类的SELECT * EXCEPT col FROM tbl之类,那就太好了。
但是,目前尚未在MS Sql Server中实现该功能。

但是,可以简化该SQL。并且仅使用1 CTE。

由于TOP 1 WITH TIES可以与ORDER BY ROW_NUMBER() OVER (...)结合使用。

这样,您就没有RN列要从最终结果中排除。

with T as (
   select TOP 1 WITH TIES
    col1, col2, col3, col4, col5, col6, col7, col8, col9, col10
   from orders_tbl
   where order_date > getdate()
   ORDER BY row_number() over(partition by col1 order by col8 DESC, col9)
)
select *
from T
order by col1, col2;

请注意,此处仅需要CTE,因为最终结果仍然必须由col1,col2排序。

旁注一:

对于简单查询,似乎更经常使用外部查询中的必填字段。

with CTE as (
   select *
   , row_number() over(partition by col1 order by col8 DESC, col9) as rn
   from orders_tbl
   where order_date > getdate()
)
select col1, col2, col3, col4, col5, col6, col7, col8, col9, col10
from CTE
where rn = 1
order by col1, col2;

旁注二:

我很想看到有一天在SQL标准中添加了类似TeraDataQUALIFY子句。当需要基于窗口函数(如ROW_NUMBER或DENSE_RANK)进行过滤时,这是一件好事。

在TeraData中,SQL可以像这样被高尔夫编码:

select col1, col2, col3, col4, col5, col6, col7, col8, col9, col10
from orders_tbl
where order_date > current_timestamp
QUALIFY row_number() over(partition by col1 order by col8 DESC, col9) = 1
order by col1, col2

答案 1 :(得分:0)

一种方法是先select into个新表,然后再drop列:

select col1, col2, col3, col4, col5, col6, col7, col8, col9, col10, row_number() over(partition by col1 order by col8 DESC, col9) rn
into #a
from orders_tbl
where order_date > getdate()

alter table #a drop column col1

select * from #a

请注意,这并不是最佳性能,因为您已经阅读然后删除了一些数据。但这对于很少的数据和即时查询非常方便。