Where are you storing these queries if you're not using stored procedures? Or is that you don't have rights to create sp's? for #1 and 2 Since it's not in an sp, I imagine you are building the sql dynamically in the app before passing it in - in that case, these can be done there. [and I assume you mean ranked by any column, since you'll typically want to order by the rank...] Make sure each column that would potentially be ranked has an index. for #4 (using population as an example): select * from ( SELECT T1.CountryName, T1.Population, T1.Hemisphere, (SELECT Count(T2.CountryName) FROM Country as T2 WHERE T2.Population <= T1.Population) as r FROM Country as T1 ) rankedSet (CountryName, Population, Hemisphere, r) where r>=3 and r<=8 order by r [quoted text, click to view] "Abdullah Kauchali" <abdullah.kauchali@someplace.com> wrote in message news:%23rLFCGyJEHA.1392@TK2MSFTNGP09.phx.gbl... > (Script at the end of this message). > > How do I do the following: > > 1. Select the required table rows based on a criteria (WHERE clause) > 2. Order by *any* column > 3. Rank the above results beginning with 1 to ... whatever > 4. Select ONLY the values between 3 and 8 of the Rank (including). > > Provisos: > 1. No stored procs; > 2. No creation of new tables > > So far, I have managed to struggle to this query: > > SELECT T1.CountryName, T1.Population, T1.Hemisphere, > (SELECT Count(T2.CountryName) + 1 > FROM Country as T2 > WHERE T2.CountryName < T1.CountryName) as r > FROM Country as T1 > ORDER BY r > > which yields this: > > CountryName Population Hem.. r > ----------- ---------- --- -- > ANGOLA 6495000 S 1 > BRAZIL 480000000 S 2 > CANADA 387474 N 3 > EGYPT 34000 N 4 > GERMANY 4300500 N 5 > PERU 48857 S 6 > SPAIN 474400 N 7 > UGANDA 498575 N 8 > UK 764000 N 9 > USA 40000000 N 10 > > Any help from here? > > Many thanks and kind regards, > > Abdullah > > <script> > CREATE TABLE Country ( > CountryName varchar(50) NOT NULL, > Population int NULL, > Hemisphere varchar(1) NULL > ) > go > > > ALTER TABLE Country > ADD PRIMARY KEY (CountryName) > go > > > > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('USA', > '40000000', 'N'); > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('CANADA', > '387474', 'N'); > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('BRAZIL', > '480000000', 'S'); > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('PERU', > '48857', 'S'); > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('UGANDA', > '498575', 'N'); > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('UK', > '764000', 'N'); > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('EGYPT', > '34000', 'N'); > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('GERMANY', > '4300500', 'N'); > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('SPAIN', > '474400', 'N'); > INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('ANGOLA', > '6495000', 'S'); > </script> > > >
You can wrap your existing query in a derived table & do: SELECT * FROM ( SELECT T1.CountryName, T1.Population, T1.Hemisphere, ( SELECT COUNT(T2.CountryName) + 1 FROM Country AS T2 WHERE T2.CountryName < T1.CountryName ) FROM Country T1 ) D ( CountryName, Population, Hemisphere, rank ) WHERE rank BETWEEN 3 AND 8 ORDER BY rank; You can also use the subquery in your WHERE clause like: SELECT T1.CountryName, T1.Population, T1.Hemisphere FROM Country T1 WHERE ( SELECT COUNT(T2.CountryName) + 1 FROM Country AS T2 WHERE T2.CountryName < T1.CountryName ) BETWEEN 3 AND 8 ; -- Anith
Well, when you add a filter in the outer query, you need to have the same filter in your sub-query or have it as a correlation. So the correct SQL statement would be: SELECT * FROM ( SELECT T1.CountryName, T1.Population, T1.Hemisphere, ( SELECT COUNT( * ) + 1 FROM Country AS T2 WHERE T2.Hemisphere = T1.Hemisphere AND T2.CountryName < T1.CountryName ) FROM Country T1 WHERE T1.Hemisphere = 'N' ) D ( CountryName, Population, Hemisphere, rank ) WHERE rank BETWEEN 3 AND 8 ORDER BY rank; -- Anith
(Script at the end of this message). How do I do the following: 1. Select the required table rows based on a criteria (WHERE clause) 2. Order by *any* column 3. Rank the above results beginning with 1 to ... whatever 4. Select ONLY the values between 3 and 8 of the Rank (including). Provisos: 1. No stored procs; 2. No creation of new tables So far, I have managed to struggle to this query: SELECT T1.CountryName, T1.Population, T1.Hemisphere, (SELECT Count(T2.CountryName) + 1 FROM Country as T2 WHERE T2.CountryName < T1.CountryName) as r FROM Country as T1 ORDER BY r which yields this: CountryName Population Hem.. r ----------- ---------- --- -- ANGOLA 6495000 S 1 BRAZIL 480000000 S 2 CANADA 387474 N 3 EGYPT 34000 N 4 GERMANY 4300500 N 5 PERU 48857 S 6 SPAIN 474400 N 7 UGANDA 498575 N 8 UK 764000 N 9 USA 40000000 N 10 Any help from here? Many thanks and kind regards, Abdullah <script> CREATE TABLE Country ( CountryName varchar(50) NOT NULL, Population int NULL, Hemisphere varchar(1) NULL ) go ALTER TABLE Country ADD PRIMARY KEY (CountryName) go INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('USA', '40000000', 'N'); INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('CANADA', '387474', 'N'); INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('BRAZIL', '480000000', 'S'); INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('PERU', '48857', 'S'); INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('UGANDA', '498575', 'N'); INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('UK', '764000', 'N'); INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('EGYPT', '34000', 'N'); INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('GERMANY', '4300500', 'N'); INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('SPAIN', '474400', 'N'); INSERT INTO Country (CountryName, Population, Hemisphere) VALUES ('ANGOLA', '6495000', 'S'); </script>
[quoted text, click to view] "Anith Sen" <anith@bizdatasolutions.com> wrote in message news:e$3AChyJEHA.3380@TK2MSFTNGP09.phx.gbl... > You can wrap your existing query in a derived table & do: > > SELECT * > FROM ( > SELECT T1.CountryName, T1.Population, T1.Hemisphere, > ( SELECT COUNT(T2.CountryName) + 1 > FROM Country AS T2 > WHERE T2.CountryName < T1.CountryName ) > FROM Country T1 > ) D ( CountryName, Population, Hemisphere, rank ) > WHERE rank BETWEEN 3 AND 8 > ORDER BY rank;
Hi Anith, Many thanks for the reply. If I append a where clause, the ranking still happens with the original non-filtered list. The sequencing gets broken. So: SELECT * FROM ( SELECT T1.CountryName, T1.Population, T1.Hemisphere, ( SELECT COUNT(T2.CountryName) + 1 FROM Country AS T2 WHERE T2.CountryName < T1.CountryName ) FROM Country T1 Where T1.Hemisphere = 'N' ) D ( CountryName, Population, Hemisphere, rank ) WHERE rank BETWEEN 3 AND 8 ORDER BY rank; results in: CANADA 387474 N 3 EGYPT 34000 N 4 GERMANY 4300500 N 5 SPAIN 474400 N 7 UGANDA 498575 N 8 what I am hoping of getting is: GERMANY 4300500 N 3 SPAIN 474400 N 4 UGANDA 498575 N 5 UK 764000 N 6 USA 40000000 N 7 Abdullah
[quoted text, click to view] "Trey Walpole" <treyNOpole@SPcomcastAM.net> wrote in message > Where are you storing these queries if you're not using stored procedures? > Or is that you don't have rights to create sp's?
Hi Trey, The queries have always been in SQL - in the code. We've never used sp's ... after googling for this, I found some answers with sp's - which we can't use. [quoted text, click to view] > for #1 and 2 > Since it's not in an sp, I imagine you are building the sql dynamically in > the app before passing it in - in that case, these can be done there.
That's fine. [quoted text, click to view] > for #4 (using population as an example): > > select * from > ( > SELECT T1.CountryName, T1.Population, T1.Hemisphere, > (SELECT Count(T2.CountryName) > FROM Country as T2 > WHERE T2.Population <= T1.Population) as r > FROM Country as T1 > ) rankedSet (CountryName, Population, Hemisphere, r) > where r>=3 and r<=8 > order by r
Is it possible to do a complete query (with where clauses e.g. where Hemisphere = 'N') and *then* do the ranking, and thereafter the "where r>=3 and r<=8")? Many thanks Abdullah
[quoted text, click to view] "Anith Sen" <anith@bizdatasolutions.com> wrote in message > Well, when you add a filter in the outer query, you need to have the same > filter in your sub-query or have it as a correlation. So the correct SQL > statement would be: > > SELECT * > FROM ( SELECT T1.CountryName, T1.Population, T1.Hemisphere, > ( SELECT COUNT( * ) + 1 > FROM Country AS T2 > WHERE T2.Hemisphere = T1.Hemisphere > AND T2.CountryName < T1.CountryName ) > FROM Country T1 > WHERE T1.Hemisphere = 'N' > ) D ( CountryName, Population, Hemisphere, rank ) > WHERE rank BETWEEN 3 AND 8 > ORDER BY rank;
Anith, Thanks for that! What help!!! :) As long as the "where" conditions are the same for both queries, it works like a charm - as you explained. It seems, though, that I can only order by one column at a time by using the correct column in "AND T2.[ColumnName] < T1.[ColumnName"). This is not so much a problem - would have been nice to have to allow "order by column1, column 2.. etc." before doing the ranking. Anyway, what do you think about using this query for substituting ADO Recordset paging? Regards Abdullah
[quoted text, click to view] >> It seems, though, that I can only order by one column at a time by using
the correct column << Actually, you can do the ranking on as many columns as you need. Please post a repro with DDLs & sample data which requires such multiple columns in the sub-query. For example, the subquery's WHERE clause for ranks involving more than one column, would be along the lines of: WHERE t1.col1 <= t2.col1 OR (t1.col1 = t2.col1 AND t1.col2 <= t2.col2) OR (t1.col1 = t2.col1 AND t1.col2 = t2.col2 AND t1.col3 <= t2.col3) OR ... [quoted text, click to view] >> what do you think about using this query for substituting ADO Recordset
paging? << Depending on your requirements, you can use this method. But make sure to test it thoroughly for performance, since complex comparison routines on larger datasets can slow things up. Here is another link which shows different approaches for paging: http://www.aspfaq.com/show.asp?id=2120 -- Anith
[quoted text, click to view] "Anith Sen" wrote
(Apol for delayed response.) [quoted text, click to view] > Depending on your requirements, you can use this method. But make sure to > test it thoroughly for performance, since complex comparison routines on > larger datasets can slow things up.
Again correct. I just tested this query on a moderately large table and the results were disappointing. It seems, the count(*) + 1 simulates "row-by-row" operation and SQL Server starts thrashing. [quoted text, click to view] >Here is another link which shows >different approaches for paging: http://www.aspfaq.com/show.asp?id=2120 Great link. Got this query from there: SELECT TOP 10 CountryName, Population, Hemisphere FROM (SELECT TOP 30 CountryName, Population, Hemisphere FROM Country -- put-where-clause-here: WHERE Country LIKE '%'+'U'+'%' ORDER BY CountryName Desc) A -- put order by here ORDER BY CountryName Desc -- must match above This one is infinitely more efficient than the previous one. Also, the syntax for ORDER BY is now simplified. Many thanks and kind regards Abdullah
[quoted text, click to view] "Anith Sen" wrote
(Apol for delayed response.) [quoted text, click to view] > Depending on your requirements, you can use this method. But make sure to > test it thoroughly for performance, since complex comparison routines on > larger datasets can slow things up.
Again correct. I just tested this query on a moderately large table and the results were disappointing for using it as a substitute for ADO Recordset paging. It seems, the count(*) + 1 simulates a "row-by-row" operation and SQL Server starts thrashing. [quoted text, click to view] >Here is another link which shows >different approaches for paging: http://www.aspfaq.com/show.asp?id=2120 Great link. Got this query from there: SELECT CountryName, Population, Hemisphere FROM (SELECT TOP 2 CountryName, Population, Hemisphere FROM (SELECT TOP 2 CountryName, Population, Hemisphere FROM Country WHERE Population > '34000' AND Hemisphere like '%N%' ORDER BY Population Asc) A -- MUST BE OPPOSITE OF B ORDER BY Population Desc) B -- MUST BE OPPOSITE OF A ORDER BY Population Asc -- ORDER BY NOW SIMPLER This one is infinitely more efficient than the previous one. The only "tricky" part is to determine the final page: if ((resultset<pagesize) or (checkForDuplicates(previousResultSet)) then eof where checkForDuplicates will return a true even if ONE record from the previous resultset is contained in the current resultset. Is there a simpler way to determine eof? Many thanks and kind regards Abdullah
Don't see what you're looking for? Try a search.
|