1

I face this question every time when I do a lot of complex processing and lot of columns SELECT ed in a sub-query but finally need to show only few. Is there anyway SQL (Oracle or Microsoft or others) is thinking of having an (extra) clause to just ignore the columns not required.

;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

Now, imagine something like this -

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

Your thoughts please?

ranit.b
  • 217
  • 3
  • 8
  • 9
    No. The answer is to not use `*` and to list out **only** the columns you want returned. There is no "`* (apart from this column)`" syntax. – Thom A Feb 11 '19 at 10:49
  • I know it's not there currently, but don't you think it'll really save bit of extra rework and bytes (more/less) of storage space. Just thinking differently and another view-point. – ranit.b Feb 11 '19 at 10:51
  • With storage on your SQL Server, the size of the definition of your objects is probably one of your lowest worries. A "few" bytes is nothing compared to the scale of other things (such as your row data) stored in a database. – Thom A Feb 11 '19 at 10:52
  • 3
    One of the issues, were it to be introduced, is that adding or removing columns in the schema would cause potentially unexpected changes to the number of columns return by a query, without any changes to the query itself. – Diado Feb 11 '19 at 10:54
  • @ranit.b no it won't. That's why it was never added to the language in almost 40 years. If you can write `except those` you can write `just those`. The query itself would break if one of the `except` columns was removed – Panagiotis Kanavos Feb 11 '19 at 10:54
  • True, and that's why it's of my lesser concern than the former one. Could be an add-on flexibility in later upgrades. – ranit.b Feb 11 '19 at 10:55
  • @Panagiotis - If nothing has been added in "almost 40 years", doesn't guarantee that it won't be added in future years! – ranit.b Feb 11 '19 at 10:56
  • @ranit.b that would be a bad idea, which is why it was never added. It would introduce *in*flexibility. Right now, the query optimizer sees which columns are really needed and excludes those that aren't wanted. – Panagiotis Kanavos Feb 11 '19 at 10:56
  • 2
    I would have no expectation that this syntax will ever be introduced if I were you, ranit.b. @Diado gives a great reason as to why; many of us have been "stung" by unexpected behaviour all because someone used `*` in a deployed object, and the underlying DDL had changed. – Thom A Feb 11 '19 at 10:56
  • This is something I'd kick up the stack. I wouldn't do it in the database, rather I'd do it in the app calling the database. For that reason, an extension of SQL that let me do this wouldn't be quite as useful. – Adam Feb 11 '19 at 10:57
  • 3
    A great new feature in Visual Studio would be to mark `select * ` as error and refuse to compile – GuidoG Feb 11 '19 at 10:58
  • @Panagiotis, Agreed. So what i'm thinking is changing the way optimizer works. May be i'm missing something fundamental. – ranit.b Feb 11 '19 at 10:58
  • If you really don't want to list out all your columns, then consider purchasing an SSMS add in that helps you. For example, I use SQL Prompt, which if I type `SELECT *` and then hit `Tab` it'll list out all the columns (with aliases) from the object in the `FROM` clause in the statement. – Thom A Feb 11 '19 at 10:59
  • 1
    You don't even need to buy an addin. Just select the query and press Ctrl+Shift+Q to brind up the designer. It will expand the columns automatically. – Panagiotis Kanavos Feb 11 '19 at 11:00
  • @Larnu, that's a sneaky one ;) Thanks – ranit.b Feb 11 '19 at 11:00
  • @ranit.b you're asking about opinions or a relational databases primer . There's no programming question to answer here. SO is a Q&A site about programming problems. A better place to ask this would be `softwareengineering.stackexchange.com` or Quora – Panagiotis Kanavos Feb 11 '19 at 11:02
  • Those example SQL's should at least use that row_number. :) Because what's the point of calculating something you don't use or even want to show. – LukStorms Feb 11 '19 at 11:02
  • @Luk, my bad. I missed adding the WHERE clause, "WHERE rn=1". Thanks for pointing. – ranit.b Feb 11 '19 at 11:04
  • Thanks for the discussion folks. It was nice hearing so many view points. Pleasure! – ranit.b Feb 11 '19 at 11:05
  • I did raise [this issue](https://feedback.azure.com/forums/908035-sql-server/suggestions/36073990-concise-syntax-for-removing-one-or-more-columns-fr) in relation to this sort of problem and `PIVOT`. Everyone saying "don't using `select *`" is ignoring a common (to me) experience that I'm just working within the `FROM` clause at that point and don't *have* a `SELECT` clause unless I artificially introduce a subquery that breaks up my query for no reason other than to be able to write that `select` clause. – Damien_The_Unbeliever Feb 11 '19 at 11:12
  • @Damien, Many thanks for your response. Nice point made in that post, but unfortunately left unnoticed. Never know, it could be brainstormed by the MS dev teams ;) – ranit.b Feb 11 '19 at 11:24
  • Possible duplicate of [SQL exclude a column using SELECT \* \[except columnA\] FROM tableA?](https://stackoverflow.com/questions/729197/sql-exclude-a-column-using-select-except-columna-from-tablea) – GSerg Feb 11 '19 at 13:15
  • @GSerg, that was my exact concern. And see the number of upvotes for that post. When I started this post, initial few comments were so critical and made me demotivated. Now it seems better. Thanks for the link. – ranit.b Feb 11 '19 at 13:43

2 Answers2

4

It would be nice if MS Sql Server supported something like a SELECT * EXCEPT col FROM tbl like Google BigQuery.
But currently that functionality isn't (yet?) implemented in MS Sql Server.

However, one can simplify that SQL. And use only 1 CTE.

Since a TOP 1 WITH TIES can be combined with an ORDER BY ROW_NUMBER() OVER (...).

That way you don't have an RN column to exclude from the final result.

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;

Note that the CTE is only needed here because the final result still has to be ordered by col1, col2.

Side-note One:

For simple queries selecting the required fields in the outer-query seems to be used more often.

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;

Side-note Two:

I would love to see something like TeraData's QUALIFY clause added someday to the SQL Standard. It's a nice thing to have when there's a need to filter based on a window function like ROW_NUMBER or DENSE_RANK.

In TeraData that SQL could be golf-coded like this:

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
LukStorms
  • 28,916
  • 5
  • 31
  • 45
  • This was something new for me. Thanks. – ranit.b Feb 11 '19 at 11:47
  • Just saw your updated answer with Google's BigQuery reference. Cool stuff! Glad that we are thinking alike. This's what I was referring to but didn't know BigQuery had that. Many thanks. :) – ranit.b Feb 11 '19 at 13:33
  • To those who down voted - Does it make any sense to you now what I was referring to? – ranit.b Feb 11 '19 at 13:35
  • Well, not sure why the downvotes. But maybe because, without sample data nor expected results, it looks to them as an incomplete question. Although I thought it was clear enough, and you did put some effort into trying to write the query. Yeah, it's harder to gain reputation through questions than it is with answers. (and answers are easier to delete to regain the rep) (and by downvoting an answer you loose 1 reputation yourself, but 0 rep by downvoting a question) – LukStorms Feb 11 '19 at 13:42
  • No, I'm least worried about points. But it somehow demotivated me as a new joinee that w/o knowing the reason people just down vote. I'm here to learn and agree doubts can be blunt at times. I've been into Oracle (SQL and PL/SQL) forums for long time, learnt a lot from community :) – ranit.b Feb 11 '19 at 13:46
  • Well, sometimes people come back to the question and then remove that downvote if the question improved. I can understand it doesn't feel nice to new people. Since they would be the first to DARE post something that doesn't look like an "usefull" question. ;) – LukStorms Feb 11 '19 at 13:51
  • Having analytic function in ORDER BY clause has been included starting which version of SQL Server ? Sorry, don't have any installation handy right now. I couldn't find the syntax in the link you posted. – ranit.b Feb 11 '19 at 19:55
  • 1
    Well, it works on 2012. But can't test it on a 2008. It should work on a 2008 though, since ORDER BY is processed after the window functions. So don't see why not. – LukStorms Feb 11 '19 at 20:13
  • I've never seen this usage anywhere. Great learning for today. :) Thanks Luk. – ranit.b Feb 11 '19 at 20:28
0

One way is to select into a new table and then drop the columns:

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

Note that this is not optimal in performance, as you've already read and then deleted some data. But it proves handy for few data and on-the-fly queries.

George Menoutis
  • 6,894
  • 3
  • 19
  • 43