Sql 如何选择每个组(分区)的前1条记录

Sql 如何选择每个组(分区)的前1条记录,sql,ms-access,ms-access-2010,ms-access-2013,Sql,Ms Access,Ms Access 2010,Ms Access 2013,我有一个名为tblRoutes的表,它包含一个唯一的from和to路由列表f=from;t=至: | fCity | fState | tCity | tState | |========|========|========|========| |New York| NY | Miami | CA | |Houston | TX |New York| NY | ... 然后我有一个名为tblCarrierRates的表格,列出了运营商在某些航线上提供的一系

我有一个名为tblRoutes的表,它包含一个唯一的from和to路由列表f=from;t=至:

| fCity  | fState | tCity  | tState |
|========|========|========|========|
|New York|   NY   | Miami  |   CA   |
|Houston |   TX   |New York|   NY   |
...
然后我有一个名为tblCarrierRates的表格,列出了运营商在某些航线上提供的一系列等级和费率:

| fCity  | fState | tCity  | tState | Tier | Rate | CarrID |  CarrName   |
|========|========|========|========|======|======|========|=============|
|New York|   NY   | Miami  |   CA   |   2  | $2.99|  ABCD  | Abracadabra |
|New York|   NY   | Miami  |   CA   |   1  | $3.00|  BUMP  | Bumpy Rides |
|Houston |   TX   |New York|   NY   |   2  | $4.00|  SLOW  |Slow Carriers|
|Houston |   TX   |New York|   NY   |   2  | $4.01|  ABCD  | Abracadabra |
...
对于tblRoutes中列出的每一条独特路线,我正在寻找tblCarrierRates提供的1条最佳路线

最佳的标准是最低级别,其次是最低比率

结果需要返回tblCarrierRates中显示的所有字段,因此基于tblRoutes中显示的上述两条路由,所需结果将是:

| fCity  | fState | tCity  | tState | Tier | Rate | CarrID |  CarrName   |
|========|========|========|========|======|======|========|=============|
|New York|   NY   | Miami  |   CA   |   1  | $3.00|  BUMP  | Bumpy Rides |
|Houston |   TX   |New York|   NY   |   2  | $4.00|  SLOW  |Slow Carriers|
我所看到的方法是按升序排列,然后进行评级,然后对fCity、fState、tCity和tState的每个独特组合的前1项记录进行匹配:

SELECT A.fCity, A.fState, A.tCity, A.tState, Q.Tier, Q.Rate, Q.CarrID, Q.CarrName
FROM tblRoutes As A LEFT JOIN 
    (SELECT TOP 1 B.CarrID, B.CarrName, B.fCity, B.fState, B.tCity, B.tState, B.Rate, B.Tier
    FROM tblCarrierRates As B
    ORDER BY tblCarrierRates.Tier ASC, tblCarrierRates.Rate ASC) As Q
ON (A.tState = Q.tState) AND (A.tCity = Q.tCity) AND (A.fState = Q.fState) AND (A.fCity = Q.fCity);
查询没有失败,但正如您可能猜到的,我编写的子查询Q只返回一条记录,而不是tblRoutes中每个路由的1条记录,因此最终结果是:

| fCity  | fState | tCity  | tState | Tier | Rate | CarrID |  CarrName   |
|========|========|========|========|======|======|========|=============|
|New York|   NY   | Miami  |   CA   |   1  | $3.00|  BUMP  | Bumpy Rides |
|Houston |   TX   |New York|   NY   |      |      |        |             |
…正如您所看到的,休斯顿到纽约之间没有匹配的结果,因为我的子查询只返回1个结果,而不是每条路线返回1个结果


如何实现我想要的结果?

您的内部查询需要按城市和州分组。这将产生每个城市1个州,允许外部联接在这些字段上联接


独立调试内部查询,直到看到预期外部查询工作的结果。首先拿出Top1,这样您就可以看到排序和分组工作正常。我会在您的内部查询中明确地添加ASC DESC,以便其他人知道您希望top工作的方向。

您可以尝试以下查询:-

SELECT fCity, fState, tCity, tState, MIN(Tier), MIN(Rate), CarrID, CarrName
FROM tblCarrierRates
GROUP BY fCity, fState, tCity, tState, CarrID, CarrName;

我相信您正在寻找类似Sql Server和Oracle的分析/窗口功能,如分区上的行数。。订购人,例如

虽然这在MS Access中没有直接提供,但我相信可以通过应用相关子查询来模拟MS Access中的行编号函数,该子查询统计具有连接筛选器定义的相同分区的行数,其中每一行通过计算同一分区中“低于”排序标准的前几行的数量进行排序:

SELECT A.fCity, A.fState, A.tCity, A.tState, Q.Tier, Q.Rate, Q.CarrID, Q.CarrName, TheRank
FROM tblRoutes As A LEFT JOIN 
    (
      SELECT B.CarrID, B.CarrName, B.fCity, B.fState, B.tCity, B.tState, B.Rate, B.Tier, 
      (
        SELECT COUNT(*) + 1
        FROM  tblCarrierRates rnk 
        -- Partition Simulation (JOIN)
        WHERE B.fCity = rnk.fCity AND B.fState = rnk.fState 
              AND B.tCity = rnk.tCity AND B.tState = rnk.tState 
              -- ORDER BY Simulation
              AND (rnk.Tier < B.Tier OR 
                 (rnk.Tier = B.Tier AND rnk.Rate < B.Rate))) AS TheRank
      FROM tblCarrierRates As B) As Q
ON (A.tState = Q.tState) AND (A.tCity = Q.tCity) 
    AND (A.fState = Q.fState) AND (A.fCity = Q.fCity)
-- Now, you just want the top rank in each partition.
WHERE TheRank = 1;
只需预先警告性能-子查询将针对每一行执行。 此外,如果存在连接,则两行都将返回

+1是以行号1开始每个分区,因为它的分区中前面的行为零

编辑,删除评论


不,那不会产生预期的结果。我认为应该。虽然我没有执行,但应该执行。是的,2分钟不起作用,因为他们只专注于自己的领域independently@GordThompson我在看你在排名上其他地方提供的答案。。。我正在尝试应用它,但我无法表达我所追求的最低层和最低速率效果:A.LaneTier>=B.LaneTier和A.Rate>=B.Rate这看起来像我所追求的,但我在FROM子句中遇到语法错误。它将tblCarrierRates中的行突出显示为B,因为QIt似乎不喜欢我添加的注释,并破坏了查询。我已经重新编写了我运行的精确工作查询。我只得到1个结果。我去掉了Rank=1的位置,看起来它并不是对fCity、fState、tCity和tstate的每个唯一组合进行排序奇怪的是,我得到了两个,完全按照我发布的SqlServer小提琴-我使用了小提琴中插入的数据,上面在MS Access中的查询你是对的,它确实有效。我发布的表和字段是我在计算机上实际得到的数据的缩写版本,因此我不得不对您的查询进行大量查找和替换。我想我一定是在什么地方没有正确地转换它。
SELECT A.fCity, A.fState, A.tCity, A.tState, Q.Tier, Q.Rate, Q.CarrID, Q.CarrName, TheRank
FROM tblRoutes As A LEFT JOIN 
    (
      SELECT B.CarrID, B.CarrName, B.fCity, B.fState, B.tCity, B.tState, B.Rate, B.Tier, 
      (
        SELECT COUNT(*) + 1
        FROM  tblCarrierRates rnk 
        WHERE B.fCity = rnk.fCity AND B.fState = rnk.fState 
              AND B.tCity = rnk.tCity AND B.tState = rnk.tState 
              AND (rnk.Tier < B.Tier OR 
                 (rnk.Tier = B.Tier AND rnk.Rate < B.Rate))) AS TheRank
      FROM tblCarrierRates As B) As Q
ON (A.tState = Q.tState) AND (A.tCity = Q.tCity) 
    AND (A.fState = Q.fState) AND (A.fCity = Q.fCity)
WHERE TheRank = 1