Access子查询出现额外记录:新手SQL开发者求查询解决方案
嘿,我完全懂你这种卡了好几天的烦躁!你的问题核心在于:当同一个Store+Product_Type组里有多个记录共享最小Despatch_Time时,普通的关联查询会把这些记录都拉出来,导致行数超过预期的200行。咱们得想办法让每组强制只返回一条,哪怕有多个相同的最小时间记录。
最通用的解决方案:窗口函数(适合大多数SQL数据库)
如果你的数据库支持窗口函数(比如SQL Server、MySQL 8+、PostgreSQL等),用ROW_NUMBER()是最直观的办法:
SELECT * FROM ( SELECT *, -- 按Store和Product_Type分组,先按Despatch_Time取最小的,再按Despatch_Type排序(你可以换成其他字段) ROW_NUMBER() OVER (PARTITION BY Store, Product_Type ORDER BY Despatch_Time ASC, Despatch_Type ASC) AS row_rank FROM table WHERE day_num = [Forms]![FRM_SomeForm]![combo_del_day] AND start_week = [Forms]![FRM_SomeForm]![txt_date1] ) AS ranked_records WHERE row_rank = 1; -- 只保留每组的第一条
这个查询里,PARTITION BY帮你把数据按Store和Product_Type分成一个个小组,ORDER BY先确保最小的Despatch_Time排在前面,再加个Despatch_Type(或者你觉得合适的其他字段,比如ID)作为“平局决胜项”,这样即使时间相同,也能确定唯一的一条记录被选中。
针对Access的特殊写法(因为你用了表单引用)
如果你是在Microsoft Access里操作,旧版本可能不支持窗口函数,那可以用TOP 1子查询来实现:
SELECT * FROM table AS A WHERE A.ID IN ( SELECT TOP 1 t.ID FROM table t WHERE t.Store = A.Store AND t.Product_Type = A.Product_Type AND t.day_num = [Forms]![FRM_SomeForm]![combo_del_day] AND t.start_week = [Forms]![FRM_SomeForm]![txt_date1] -- 同样先按时间排序,再加平局决胜字段 ORDER BY t.Despatch_Time ASC, t.Despatch_Type ASC );
这个思路是:对每个Store+Product_Type组,先筛选出符合日期条件的记录,按时间和决胜字段排序后取第一条的ID,最后外层查询用这些ID拉取完整记录,保证每组只返回一条。
关键提醒
你可以根据自己的需求调整平局决胜的字段——比如如果想优先选Despatch_Type为某个特定值的记录,就把ORDER BY里的Despatch_Type ASC改成CASE WHEN Despatch_Type = '你要的类型' THEN 0 ELSE 1 END,这样目标类型会排在最前面被选中。
内容的提问来源于stack exchange,提问作者Master Sketchiggle

