按记录计数每个前5个组的首要项目(Access SQL)

时间:2016-09-06 16:30:41

标签: sql ms-access

我有一张大表Audit,其中包含数千条拒绝声明的记录。每个人都来自供应商,并有拒绝理由和地位。只有id是唯一的。

id |      denial      |   supplier    | status
---|------------------|---------------|---------
 1 | Duplicate claim  | ACME          | Adjusted
 2 | Not authorized   | Umbrella Corp | Adjusted
 3 | Not authorized   | Stark Ind.    | Adjusted
 4 | Rec'd after due  | ACME          | Override
 5 | Duplicate claim  | Stark Ind.    | Adjusted
... etc

我需要的是按记录计数“调整”状态声明的前5个拒绝原因,以及每个拒绝原因的记录计数的最高提供者。

denial          | cnt_denial | top_supplier  | cnt_top_supplier
----------------|------------|---------------|-----------------
Not authorized  | 917        | Stark Ind.    | 351
Duplicate claim | 685        | Stark Ind.    | 195
Not in contract | 525        | ACME          | 216
Rec'd after due | 512        | Umbrella Corp | 500
Explosions      | 349        | ACME          | 231

我尝试了很多方法,主要是尝试调整其他类似的解决方案,但是我在这里超越了我微薄的SQL知识而感到沮丧。我尝试过的几种解决方案在MS Access(2010)中不起作用。我创建了两个查询作为开始,但是我无法以我需要的方式加入它们。

此查询完全返回我需要的拒绝原因数据:

SELECT TOP 5 denial, Count(*) AS cnt_denial
FROM Audit
GROUP BY status, denial
HAVING status="Adjusted"
ORDER BY Count(*) DESC;

此查询包含表中每个拒绝/供应商分组的计数。我不确定如何获得每个拒绝原因的顶级供应商,这似乎应该很简单,但我遇到了麻烦。编辑:这是我的主要问题。如果我能够获得每个拒绝原因的顶级单一供应商,我可以找出加入。我尝试过使用MAX但还没有成功。 / EDIT

SELECT denial, supplier, Count(*) AS cnt_supplier
FROM Audit
GROUP BY denial, supplier, status
HAVING status="Adjusted"
ORDER BY Count(*) DESC;

我需要一个查询,因为我只是通过ADO从Excel传递此信息。任何帮助都将非常感激。

3 个答案:

答案 0 :(得分:1)

我不知道这是否是完全有效的Access SQL。如果不是这样的话,它不需要太多调整:

select
    d.denial,
    d.cnt_denial,
    ds.supplier as top_supplier,
    ds.cnt_supplier as cnt_top_supplier
from
    (
        select top 5 denial, count(*) as cnt_denial
        from Audit
        where status = 'Adjusted'
        group by denial
        order by count(*) desc
    ) d
    inner join
    (
        select denial, supplier, count(*) as cnt_supplier
        from Audit
        where status = 'Adjusted'
        group by denial, supplier
    ) ds
        on ds.denial = d.denial
where not exists (
    select 1
    from Audit as a2
    where a2.status = 'Adjusted'
        and a2.denial = ds.denial and a2.supplier <> ds.supplier
    group by a2.supplier
    having count(*) > ds.cnt_supplier
        /* or count(*) = ds.cnt_supplier and a2.supplier < ds.supplier -- tiebreaker */
)
order by d.cnt_denial desc, ds.supplier

通过使用top 5,无论关系如何,它都只抓取五行。然后使用子查询处理每个组的前1个,在这种情况下,您将包含tie并可能在最终结果中检索超过5行。如果您需要或在供应商排名中打破关系并将其排除,那么在拒绝级别包含关系并不太困难。

编辑:我将一些测试数据汇总在一起,并且打破平局似乎可以在SQL Server上运行。 http://rextester.com/ZEWJ43486

答案 1 :(得分:0)

看起来你已经完成了所有艰苦的工作。

一种解决方案是在第二个查询中测试拒绝原因包含

将您的第一个查询保存为 qTop5Reasons

SELECT TOP 5 denial, Count(*) AS cnt_denial
FROM Audit
GROUP BY status, denial
HAVING status="Adjusted"
ORDER BY Count(*) DESC;

根据该查询中的原因修改您的第二个查询以限制结果:

SELECT Audit.denial, Audit.supplier, Count(*) AS cnt_supplier
FROM Audit
WHERE (Audit.denial In (SELECT denial FROM qTop5Reasons))
GROUP BY Audit.denial, Audit.supplier, Audit.status
HAVING (((Audit.[status])="Adjusted"))
ORDER BY Count(*) DESC;

答案 2 :(得分:0)

你应该尝试内联。试试这个

SELECT A.DENIAL, A.Cnt_Denial,B.Supplier as TOP_SUPPLIER, B.Cnt_supplier as           
TOP_CNT_SUPPLIER
FROM 
(SELECT TOP 5 denial, Count(*) AS cnt_denial
 FROM Audit
 GROUP BY status, denial
 HAVING status="Adjusted"
 ORDER BY Count(*) DESC) AS A INNER JOIN 
 (SELECT TOP 5 denial, supplier, Count(*) AS cnt_supplier
 FROM Audit
 GROUP BY denial, supplier, status
 HAVING status="Adjusted"
 ORDER BY Count(*) DESC) AS B
 ON A.DENIAL = B.DENIAL