Sql 为每组选择前1名

Sql 为每组选择前1名,sql,ms-access,query-optimization,greatest-n-per-group,Sql,Ms Access,Query Optimization,Greatest N Per Group,我有一个Access数据库,其中包含一个表,其中包含有关我们排序的零件的信息。此表有一个自动编号ID字段和一个链接到另一个包含零件信息的表的110ID。它还包含排序日期、排序移位、排序、报废和修复。我需要找出自从上次缺陷发现后,每个110ID有多少零件被分类,没有报废或修复 问题是我不能保证这些信息会按时间顺序输入数据库。因此,我需要对“sortDate”大于上一个缺陷或“sortDate”与上一个缺陷相同但大于“sortShift”的任何记录的“sortDate”字段求和,或者如果“sortD

我有一个Access数据库,其中包含一个表,其中包含有关我们排序的零件的信息。此表有一个自动编号ID字段和一个链接到另一个包含零件信息的表的110ID。它还包含排序日期、排序移位、排序、报废和修复。我需要找出自从上次缺陷发现后,每个110ID有多少零件被分类,没有报废或修复

问题是我不能保证这些信息会按时间顺序输入数据库。因此,我需要对“sortDate”大于上一个缺陷或“sortDate”与上一个缺陷相同但大于“sortShift”的任何记录的“sortDate”字段求和,或者如果“sortDate”和“sortShift”匹配,则使用自动编号id作为最后手段

这是我当前使用的查询:

SELECT SortInfo.[110ID], Sum(SortInfo.Sorted) AS SumOfSorted
FROM SortInfo
WHERE (
    ((SortInfo.sortdate)>(select top 1 dupe.sortdate from sortinfo as dupe where     (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc)))
    OR (((SortInfo.sortdate)=(select top 1 dupe.sortdate from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc)) 
        AND ((SortInfo.sortshift)>(select top 1 dupe.sortshift from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc))) 
    OR (((SortInfo.sortdate)=(select top 1 dupe.sortdate from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc)) 
        AND ((SortInfo.sortshift)=(select top 1 dupe.sortshift from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc)) 
        AND ((SortInfo.ID)>(select top 1 dupe.id from sortinfo as dupe where (((dupe.[110id])=(sortinfo.[110id])) and (((dupe.repaired)<>0) or ((dupe.scrapped)<>0))) order by dupe.sortdate desc, dupe.sortshift desc, dupe.id desc))
)
GROUP BY SortInfo.[110ID];

问题是,这是非常缓慢的。是否有更好的方法来实现这一点,从而产生更好的性能?

您可以使用左外部联接或不存在的子查询,而不是使用所有这些子查询。我不太使用Access,所以如果Access不符合ANSI标准,那么您可能需要对这些方面进行调整

SELECT
    SI.[110ID],
    SUM(SI.Sorted) AS SumOfSorted
FROM
    SortInfo SI
LEFT OUTER JOIN SortInfo SI2 ON
    SI2.Repaired <> 0 AND
    SI2.Scrapped <> 0 AND
    (
        SI2.SortDate > SI.SortDate OR
        (SI2.SortDate = SI.SortDate AND SI2.SortShift > SI.SortShift) OR
        (SI2.SortDate = SI.SortDate AND SI2.SortShift = SI.SortShift AND SI2.ID > SI.ID)
    )
WHERE
    SI2.ID IS NULL
GROUP BY
    SI.[110ID]

初步发现:我无法让选项1工作,因为逻辑需要是SI2。修复0或SI2。报废0和。。。但是,访问权限似乎不允许额外的用户对两个或多个语句进行分组。选项二似乎也不起作用,或者它同样慢。这很奇怪,它不允许使用括号。不幸的是,我无法在这台电脑上进行测试。你确定某个地方没有输入错误吗?Access/Jet/ACE对其连接语法非常挑剔。还要注意的是,“不存在”和“不存在”通常不能通过Jet很好地优化,并且可能仅在比较的一侧使用该指数。
SELECT
    SI.[110ID],
    SUM(SI.Sorted) AS SumOfSorted
FROM
    SortInfo SI
WHERE
    NOT EXISTS
    (
        SELECT *
        FROM
            SortInfo SI2
        WHERE
            SI2.Repaired <> 0 AND
            SI2.Scrapped <> 0 AND
            (
                SI2.SortDate > SI.SortDate OR
                (SI2.SortDate = SI.SortDate AND SI2.SortShift > SI.SortShift) OR
                (SI2.SortDate = SI.SortDate AND SI2.SortShift = SI.SortShift AND SI2.ID > SI.ID)
            )    
    GROUP BY
        SI.[110ID]
    )