Tom Ellison said:
Your example shows, in the last two rows, the circumstance where User,
Payee, and AcctNo are all the same, creating a tie in the ranking,
which you accurately portray in the ID column. What you don't show is
what would happen in the next row if it were for the same User but for
a different Payee and/or AcctNo. The ID value would then be 4,
skipping 3 because of the tie (just like a horse race).
This could be changed if necessary.
Your right of course.Lets do it.I'm using Sql Server 2000,
I'm sure your familiar with it
I'm also throwing in an identity (autonumber) column.
create table #TS
(rowno int identity,[User] varchar(10),Payee char(3),AcctNo varchar(10),[ID]
int null)
go
insert #TS ([User],Payee,AcctNo)Values('BOB01','PGE','1234567')
insert #TS ([User],Payee,AcctNo)Values('BOB01','PGE','7659838')
insert #TS ([User],Payee,AcctNo)Values('BOB01','SBC','555-1298')
insert #TS ([User],Payee,AcctNo)Values('BILL67','PGE','1238133')
insert #TS ([User],Payee,AcctNo)Values('BILL67','SBC','555-1234')
insert #TS ([User],Payee,AcctNo)Values('BILL67','SBC','555-1234')
-- Add extra row for 'BILL67'
insert #TS ([User],Payee,AcctNo)Values('BILL67','TLC','555-1234')
Your query and result:
SELECT [User], Payee, AcctNo,
(SELECT COUNT(*)+1 From #TS T1 WHERE
T1.[User] = T.[User] AND(T1.Payee < T.Payee OR (T1.Payee = T.Payee AND
T1.AcctNo < T.AcctNo))) AS Rank
FROM #TS T
ORDER BY t.[User],
t.Payee, t.AcctNo
User Payee AcctNo Rank
---------- ----- ---------- -----------
BILL67 PGE 1238133 1
BILL67 SBC 555-1234 2
BILL67 SBC 555-1234 2
BILL67 TLC 555-1234 4 <---
BOB01 PGE 1234567 1
BOB01 PGE 7659838 2
BOB01 SBC 555-1298 3
You can eliminate the ties with a Count(Distinct..)
SELECT [User], Payee, AcctNo,
(SELECT COUNT(Distinct cast([user] as varchar(10))+cast(Payee as
char(3))+cast(AcctNo as varchar(10)))+1 From #TS T1 WHERE
T1.[User] = T.[User] AND(T1.Payee < T.Payee OR (T1.Payee = T.Payee AND
T1.AcctNo < T.AcctNo))) AS Rank
FROM #TS T
ORDER BY t.[User],
t.Payee, t.AcctNo
(Notice that even the Server Count(Distinct..) is a half ass
implementation since it takes only one argument).
User Payee AcctNo Rank
---------- ----- ---------- -----------
BILL67 PGE 1238133 1
BILL67 SBC 555-1234 2
BILL67 SBC 555-1234 2
BILL67 TLC 555-1234 3 <--
BOB01 PGE 1234567 1
BOB01 PGE 7659838 2
BOB01 SBC 555-1298 3
Several points:
These queries are not easy to write.There's probably no
more than a dozen Access users who could do it
These kind of ranking queries become much easier to conceptualize
and code using the OLAP features of sql99 (ie.Row_number(),Rank()
and Dense_rank().Of course you won't find these features in Access
or even Sql Server 2000.You will find them in Oracle and DB2.
The RAC utility for S2k tries,among many other things, to simulate
the sql99 OLAP functions without having the user writing any sql code.
For example here's the above query in RAC:
Exec Rac
@transform='_dummy_',-- Not doing a crosstab.
-- Note here the identity column [rowno] is
-- used to make each row unique.(RAC works
-- on grouping).The sequence of columns in @rows
-- also implies the sort order.(There are other
-- options to sort).
@rows='[User] & Payee & AcctNo & [rowno]',
@pvtcol='Access Reports',
@from='#TS',
@grand_totals='n',@rowbreak='n',
-- This is the rank we want.It's a Dense_rank()
-- in sql99.The column name for it is 'test'.
@rowindicators='AcctNo{test}',
@defaultexceptions='dumy & [rowno]'
User Payee AcctNo test
------ ----- -------- -----
BILL67 PGE 1238133 1
BILL67 SBC 555-1234 2
BILL67 SBC 555-1234 2
BILL67 TLC 555-1234 3 <--
BOB01 PGE 1234567 1
BOB01 PGE 7659838 2
BOB01 SBC 555-1298 3
Just my $.02 :~)
For S2k check out RAC v2.2 and QALite @
www.rac4sql.net