From: MRe on
Hi,

Is it possible to "SELECT *" just the fields of a sub-nested query
(i.e., I don't want * of a nested query, but of a nested-nested
query)?

For example (SELECT Inner.*):

----------------------------
SELECT
Inner.*
FROM
(
SELECT
Inner.*
, ROW_NUMBER() OVER ( ORDER BY x ) AS ROW
FROM
(
SELECT x
FROM y
) AS Inner
WHERE
ROW BETWEEN @Start AND @End
) AS Outer
----------------------------

So I want the result to be everything from the sub-nested query (and
not the extra fields added in the nested query).

It's an odd question, I'm sure, but I ask because I would like to
automate web-site pagination, where I was thinking I could do it by
wrapping any query in one that attaches row numbers for page
filtering, and then another to return the query back to its original
columns (while not having to actually know what columns they are)

Thank you,
Kind regards,
Eliott
From: --CELKO-- on
INNER and OUTER are reserved words in SQL. I would leave the row
numbers in the result set; if you need to drop them, do it in the
front end.

(SELECT CoreQuery.*,
ROW_NUMBER() OVER (ORDER BY x) AS display_position
FROM (SELECT ..
FROM ..
WHERE ..) AS CoreQuery
WHERE display_position BETWEEN in_start_display_position
AND in_end_display_position);

But you really ought to do pagination in the report server or front
end and not the database. We were playing around with various ways to
get a page number and line number within page. Here are some of the
answers. None have been tested, so you might want to try them and see
what happens:
REATE TABLE Foobar (x INTEGER NOT NULL);
GO
SELECT * FROM Foobar;

INSERT INTO Foobar
VALUES (39634), (62349), (74088), (65564), (16379), (19713), (39153),
(69459), (17986), (24537), (14595), (35050), (40469), (27478),
(44526), (67331), (93365), (54526), (22356), (93208), (30734),
(71571), (83722), (79712), (25775), (65178), (07763), (82928),
(31131), (30196), (64628), (89126), (91254), (24090), (25752),
(03091), (39411), (73146), (06089), (15630), (42831), (95113),
(43511), (42082), (15140), (34733), (68076), (18292), (69486),
(80468), (80583), (70361), (41047), (26792), (78466), (03395),
(17635), (09697), (82447), (31405), (00209), (90404), (99457),
(72570), (42194), (49043), (24330), (14939), (09865), (45906),
(05409), (20830), (01911), (60767), (55248), (79253), (12317),
(84120), (77772), (50103), (95836), (22530), (91785), (80210),
(34361), (52228), (33869), (94332), (83868), (61672), (65358),
(70469), (87149), (89509), (72176), (18103), (55169), (79954),
(72002), (20582), (72249), (04037), (36192), (40221), (14918),
(53437), (60571), (40995), (55006), (10694), (41692), (40581),
(93050), (48734), (34652), (41577), (04631), (49184), (39295),
(81776), (61885), (50796), (96822), (82002), (07973), (52925),
(75467), (86013), (98072), (91942), (48917), (48129), (48624),
(48248), (91465), (54898), (61220), (18721), (67387), (66575),
(88378), (84299), (12193), (03785), (49314), (39761), (99132),
(28775), (45276), (91816), (77800), (25734), (09801), (92087),
(02955), (12872), (89848), (48579), (06028), (13827), (24028),
(03405), (01178), (06316), (81916), (40170), (53665), (87202),
(88638), (47121), (86558), (84750), (43994), (01760), (96205),
(27937), (45416), (71964), (52261), (30781);
*/

BEGIN
DECLARE @page_size INTEGER;
SET @page_size = 8; -- whatever


SELECT x,(ROW_NUMBER() OVER (ORDER BY x)) AS absolute_line_nbr,

(((ROW_NUMBER() OVER (ORDER BY x) + (@page_size -1))/ @page_size))
AS page_number,
CASE WHEN (ROW_NUMBER() OVER (ORDER BY x) % @page_size) > 0
THEN (ROW_NUMBER() OVER (ORDER BY x) % @page_size)
ELSE @page_size END
AS line_number_within_page_1,
COALESCE (NULLIF (ROW_NUMBER() OVER (ORDER BY x) % @page_size, 0),
@page_size)
AS line_number_within_page_2,
@page_size + (ROW_NUMBER() OVER (ORDER BY x)
- @page_size* CEILING ((ROW_NUMBER() OVER (ORDER BY x))/ (1.0 *
@page_size)))
AS line_number_within_page_3
FROM Foobar;

--totally different approach
SELECT x, page_nbr,
ROW_NUMBER() OVER (PARTITION BY page_nbr ORDER BY x) AS line_nbr
FROM (SELECT x, ((ROW_NUMBER() OVER (ORDER BY x) + (@page_size -1))/
@page_size)
AS page_nbr
FROM Foobar) AS Pages;
END;




From: MRe on
Hi CELKO,

Thank you for the response.

> INNER and OUTER are reserved words in SQL.

Sorry, yes - I should be more careful with these things. Thanks for
the heads-up.

> I would leave the row numbers in the result set; if you need to drop them, do it in the front end.

I was hoping to avoid this so as not to upset the other developers (as
it'll be auto-generating the modifying query behind the scenes). I
suppose if it can't be done, it's not too big a price

> But you really ought to do pagination in the report server or front end and not the database

We had been doing pagination in the front-end before, and moved away
as it seemed like a bad idea because we had to hold on to the whole
record-set in session memory. Plus, as there are usually more pages
available for viewing than are actually viewed, it was wasteful.

Why do you say it should be done at the front-end?

> We were playing around with various ways to get a page number and line number within page.  Here are some of the
> answers.

Interesting. I had been working out page number (in my auto-generating
way) by wrapping the original query in a "SELECT COUNT(*) FROM
(<original query>) AS TotalEntries" and calculating the number of
pages in the front-end, but these methods look good. I will certainly
given them a try.

Thank you kindly,
Eliott
From: --CELKO-- on
>> Why do you say it should be done at the front-end? <<

1) In a tiered architecture, formatting is done in the front end and
not the DB.

2) I am used to having a report server. You write the basic query
once, throw it over the wall to the report server where it is sorted
and aggregated many different ways (totals by product, totals by
region, etc), sent out as emails (hre is your regional report), turned
into graphics (It must have a dancing bear in the top left corner of
the spreadsheet), and so forth.

This is SOOOO much faster and safer than having a ton of DB side
routines for each report.

>> these methods look good. I will certainly given them a try. <<

We have no timings on them --they were a programming exercise. Let me
know how theyw ork.

From: Erland Sommarskog on
MRe (pgdown(a)gmail.com) writes:
> Is it possible to "SELECT *" just the fields of a sub-nested query
> (i.e., I don't want * of a nested query, but of a nested-nested
> query)?

No.

You could do SELECT INTO a temp table, and then drop the row_number
column from the temp table, and then do SELECT * from the temp table.

But don't this, as this can have some performance implications on
a busy system.

> It's an odd question, I'm sure, but I ask because I would like to
> automate web-site pagination, where I was thinking I could do it by
> wrapping any query in one that attaches row numbers for page
> filtering, and then another to return the query back to its original
> columns (while not having to actually know what columns they are)

Either you pass the row number to the application (which probably
can find use for it), or list the columns explicitly. SELECT * is
after all considered bad practice.

--
Erland Sommarskog, SQL Server MVP, esquel(a)sommarskog.se

Links for SQL Server Books Online:
SQL 2008: http://msdn.microsoft.com/en-us/sqlserver/cc514207.aspx
SQL 2005: http://msdn.microsoft.com/en-us/sqlserver/bb895970.aspx
SQL 2000: http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx