在 visual foxpro 中按分区排名
Ranking by partition in visual foxpro
我有以下 table 看起来像
+ --- + --- +
| AID | Tag |
+ --- + --- +
| 1 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 820 |
| 2 | 821 |
| 3 | 2 |
| 4 | 5 |
| 4 | 18 |
| 4 | 2744|
| 4 | 2745|
+ --- + --- +
当我编写以下 SQL Server 2008 代码时
select AID,
Tag,
RANK() over (partition by AID order by Tag asc) as rank
from My_Table
它产生以下结果
+ --- + --- + ---- +
| AID | Tag | Rank |
+ --- + --- + ---- +
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 2 | 3 | 2 |
| 2 | 820 | 3 |
| 2 | 821 | 4 |
| 3 | 2 | 1 |
| 4 | 5 | 1 |
| 4 | 18 | 2 |
| 4 | 2744| 3 |
| 4 | 2745| 4 |
+ --- + --- + ---- +
这正是我想要的。
现在,我想在 Visual FoxPro 9 中编写同样的东西 SQL。我使用 recno() 进行了尝试,如 here 所示;这对我的记录进行了编号,但似乎不支持分区功能,并且 VFP 9 SQL 似乎不支持相关子查询。我知道我可以用游标和扫描来做到这一点,但我不想那样做。有什么建议吗?
VFP 中没有 rank() 函数。但是,您可以通过多种方式实现相同的效果。一种方法是简单扫描...endscan 通过更新排名值,如下例所示:
*** Sample Data
Create Cursor mytable ( AID Int, Tag Int)
Insert Into mytable Values (1,1 )
Insert Into mytable Values (2,2 )
Insert Into mytable Values (2,3 )
Insert Into mytable Values (2,820 )
Insert Into mytable Values (2,821 )
Insert Into mytable Values (3,2 )
Insert Into mytable Values (4,5 )
Insert Into mytable Values (4,18 )
Insert Into mytable Values (4,2744)
Insert Into mytable Values (4,2745)
*** Sample Data
Select AID, Tag, Cast(0 As Int) As rank ;
from mytable ;
order By AID, Tag ;
into Cursor crsRanked ;
readwrite
Scan
AID = AID
rcno = Recno()
Replace rank With Recno()-m.rcno+1 While AID = m.AID
Skip -1
Endscan
Locate
Browse
编辑:昨天我忽略了 MS SQL 服务器的 RANK() 函数是如何工作的,抱歉。这是一个像 MS SQL Server's Rank(), Dense_Rank(), Row_number():
一样工作的
Create Cursor mytable ( AID Int, Tag Int)
Insert Into mytable Values (1,1 )
Insert Into mytable Values (2,2 )
Insert Into mytable Values (2,3 )
Insert Into mytable Values (2,820 )
Insert Into mytable Values (2,821 )
Insert Into mytable Values (3,2 )
Insert Into mytable Values (4,5 )
Insert Into mytable Values (4,18 )
Insert Into mytable Values (4,18 )
Insert Into mytable Values (4,18 )
Insert Into mytable Values (4,2744)
Insert Into mytable Values (4,2745)
Select AID, Tag, ;
Cast(0 As Int) As rownum, ;
Cast(0 As Int) As rank, ;
Cast(0 As Int) As denserank ;
from mytable ;
order By AID, Tag ;
into Cursor crsRanked ;
readwrite
Local AID,rank,denserank,nextrank,rcno
Scan
AID = AID
rank = 0
nextrank = 0
denserank = 0
rcno = Recno()
Scan While m.AID = AID
Tag = Tag
rank = nextrank + 1
denserank = m.denserank + 1
Replace ;
rank With m.rank, ;
denserank With m.denserank, ;
rownum With Recno()-m.rcno+1 ;
While AID = m.AID And Tag = m.Tag
nextrank = m.nextrank + _Tally
Skip -1
Endscan
Skip -1
Endscan
Locate
Browse
我为所有想知道的人找到了答案。以下 SQL 代码在 Visual FoxPro 9.0 中受支持,并且可以满足我们的要求。
select t1.aid, ;
t1.tag, ;
count(*) as rank ;
from my_table t1 ;
inner join my_table t2 ;
on t2.aid = t1.aid ;
and t2.tag <= t1.tag ;
group by t1.aid, t1.tag
为了了解原因,让我们通过省略聚合并包括来自 t2.
的标记来仔细查看内部联接
select t1.aid, ;
t1.tag, ;
t2.tag ;
from my_table t1 ;
inner join my_table t2 ;
on t2.aid = t1.aid ;
and t2.tag <= t1.tag ;
order by t1.aid, t1.tag
这段代码产生了一个 table 像
+ --- + ---- + ---- +
| AID | Tag1 | Tag2 |
+ --- + ---- + ---- +
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 2 | 3 | 2 |
| 2 | 3 | 3 |
| 2 | 820 | 2 |
| 2 | 820 | 3 |
| 2 | 820 | 820 |
| 2 | 821 | 2 |
| 2 | 821 | 3 |
| 2 | 821 | 820 |
| 2 | 821 | 821 |
| 3 | 2 | 2 |
| 4 | 5 | 5 |
| 4 | 18 | 5 |
| 4 | 18 | 18 |
| 4 | 2744 | 5 |
| 4 | 2744 | 18 |
| 4 | 2744 | 2744 |
| 4 | 2745 | 5 |
| 4 | 2745 | 18 |
| 4 | 2745 | 2744 |
| 4 | 2745 | 2745 |
+ --- + ---- + ---- +
其实我们并不关心Tag2中的数据,但是现在可以清楚的看到rank就是Tag1[=26]中的count =] 按 Aid 和 Tag1.
分组
我有以下 table 看起来像
+ --- + --- +
| AID | Tag |
+ --- + --- +
| 1 | 1 |
| 2 | 2 |
| 2 | 3 |
| 2 | 820 |
| 2 | 821 |
| 3 | 2 |
| 4 | 5 |
| 4 | 18 |
| 4 | 2744|
| 4 | 2745|
+ --- + --- +
当我编写以下 SQL Server 2008 代码时
select AID,
Tag,
RANK() over (partition by AID order by Tag asc) as rank
from My_Table
它产生以下结果
+ --- + --- + ---- +
| AID | Tag | Rank |
+ --- + --- + ---- +
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 2 | 3 | 2 |
| 2 | 820 | 3 |
| 2 | 821 | 4 |
| 3 | 2 | 1 |
| 4 | 5 | 1 |
| 4 | 18 | 2 |
| 4 | 2744| 3 |
| 4 | 2745| 4 |
+ --- + --- + ---- +
这正是我想要的。
现在,我想在 Visual FoxPro 9 中编写同样的东西 SQL。我使用 recno() 进行了尝试,如 here 所示;这对我的记录进行了编号,但似乎不支持分区功能,并且 VFP 9 SQL 似乎不支持相关子查询。我知道我可以用游标和扫描来做到这一点,但我不想那样做。有什么建议吗?
VFP 中没有 rank() 函数。但是,您可以通过多种方式实现相同的效果。一种方法是简单扫描...endscan 通过更新排名值,如下例所示:
*** Sample Data
Create Cursor mytable ( AID Int, Tag Int)
Insert Into mytable Values (1,1 )
Insert Into mytable Values (2,2 )
Insert Into mytable Values (2,3 )
Insert Into mytable Values (2,820 )
Insert Into mytable Values (2,821 )
Insert Into mytable Values (3,2 )
Insert Into mytable Values (4,5 )
Insert Into mytable Values (4,18 )
Insert Into mytable Values (4,2744)
Insert Into mytable Values (4,2745)
*** Sample Data
Select AID, Tag, Cast(0 As Int) As rank ;
from mytable ;
order By AID, Tag ;
into Cursor crsRanked ;
readwrite
Scan
AID = AID
rcno = Recno()
Replace rank With Recno()-m.rcno+1 While AID = m.AID
Skip -1
Endscan
Locate
Browse
编辑:昨天我忽略了 MS SQL 服务器的 RANK() 函数是如何工作的,抱歉。这是一个像 MS SQL Server's Rank(), Dense_Rank(), Row_number():
一样工作的Create Cursor mytable ( AID Int, Tag Int)
Insert Into mytable Values (1,1 )
Insert Into mytable Values (2,2 )
Insert Into mytable Values (2,3 )
Insert Into mytable Values (2,820 )
Insert Into mytable Values (2,821 )
Insert Into mytable Values (3,2 )
Insert Into mytable Values (4,5 )
Insert Into mytable Values (4,18 )
Insert Into mytable Values (4,18 )
Insert Into mytable Values (4,18 )
Insert Into mytable Values (4,2744)
Insert Into mytable Values (4,2745)
Select AID, Tag, ;
Cast(0 As Int) As rownum, ;
Cast(0 As Int) As rank, ;
Cast(0 As Int) As denserank ;
from mytable ;
order By AID, Tag ;
into Cursor crsRanked ;
readwrite
Local AID,rank,denserank,nextrank,rcno
Scan
AID = AID
rank = 0
nextrank = 0
denserank = 0
rcno = Recno()
Scan While m.AID = AID
Tag = Tag
rank = nextrank + 1
denserank = m.denserank + 1
Replace ;
rank With m.rank, ;
denserank With m.denserank, ;
rownum With Recno()-m.rcno+1 ;
While AID = m.AID And Tag = m.Tag
nextrank = m.nextrank + _Tally
Skip -1
Endscan
Skip -1
Endscan
Locate
Browse
我为所有想知道的人找到了答案。以下 SQL 代码在 Visual FoxPro 9.0 中受支持,并且可以满足我们的要求。
select t1.aid, ;
t1.tag, ;
count(*) as rank ;
from my_table t1 ;
inner join my_table t2 ;
on t2.aid = t1.aid ;
and t2.tag <= t1.tag ;
group by t1.aid, t1.tag
为了了解原因,让我们通过省略聚合并包括来自 t2.
的标记来仔细查看内部联接select t1.aid, ;
t1.tag, ;
t2.tag ;
from my_table t1 ;
inner join my_table t2 ;
on t2.aid = t1.aid ;
and t2.tag <= t1.tag ;
order by t1.aid, t1.tag
这段代码产生了一个 table 像
+ --- + ---- + ---- +
| AID | Tag1 | Tag2 |
+ --- + ---- + ---- +
| 1 | 1 | 1 |
| 2 | 2 | 2 |
| 2 | 3 | 2 |
| 2 | 3 | 3 |
| 2 | 820 | 2 |
| 2 | 820 | 3 |
| 2 | 820 | 820 |
| 2 | 821 | 2 |
| 2 | 821 | 3 |
| 2 | 821 | 820 |
| 2 | 821 | 821 |
| 3 | 2 | 2 |
| 4 | 5 | 5 |
| 4 | 18 | 5 |
| 4 | 18 | 18 |
| 4 | 2744 | 5 |
| 4 | 2744 | 18 |
| 4 | 2744 | 2744 |
| 4 | 2745 | 5 |
| 4 | 2745 | 18 |
| 4 | 2745 | 2744 |
| 4 | 2745 | 2745 |
+ --- + ---- + ---- +
其实我们并不关心Tag2中的数据,但是现在可以清楚的看到rank就是Tag1[=26]中的count =] 按 Aid 和 Tag1.
分组