Sql 如何选择每个组(分区)的前1条记录
我有一个名为tblRoutes的表,它包含一个唯一的from和to路由列表f=from;t=至: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的表格,列出了运营商在某些航线上提供的一系
| 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