【问题标题】:MS Access query to filter duplicates with criteria使用条件过滤重复项的 MS Access 查询
【发布时间】:2016-09-26 07:09:42
【问题描述】:

我有 2 个表,1Poolwaitingexchange 和 VA05(ZRAX),如下面的链接所示。

http://i.stack.imgur.com/FN9tM.png

我需要来自 VA05(ZRAX) 的 [Vcat],这两个表之间的关系来自 [Material Code]->[Description1] 和 [Cust PO] -> [PO Number](也显示在链接中)

唯一的问题是,对于每个 [Material Code] 和 [Cust PO],可能存在具有不同 [Vcat] 的重复项,这意味着除了 [Vcat] 之外的所有字段都相同,我想要 Vcat 最低的记录但不是零。

例如。如果重复记录有[Vcat] 0、1、2、3,我想选择显示[Vcat]为1的记录。

如果记录只有 [Vcat] 0,我希望它显示 [Vcat] 为 0 的记录

如果 [Vcat] 为空,则返回 [Vcat] 为空的记录。

唯一唯一的记录是表 1 中的 [Notif#],我尝试了很多不同的方法,例如按 [Notif#] 分组,首先是每个重复字段,MIN 是 [Vcat],但我只能'没有得到我想要的值。

我的 SQL 知识不存在,我做了很多试验和错误,希望有人能帮助我解决这个问题。

【问题讨论】:

  • 请显示当前数据、任何 SQL 尝试和期望的结果。文字解释很难解释。

标签: sql ms-access duplicates criteria


【解决方案1】:

您有三个案例可以一起UNION。毫无疑问,有人会想出一个SELECT,它可以用IFFs 和ORs 完成这三个方面,但你可能会发现UNION 方法更容易遵循,特别是如果你不知道SQL .

为了自己的方便,我更改了一些名称,并使用了-999,因为我避免使用空值:

SELECT p.Material_Code, p.Cust_PO, 1 AS VCat
  FROM Pool p
 WHERE EXISTS ( SELECT *
                  FROM VARAX v
                 WHERE v.Material_Code = p.Material_Code
                       AND v.Cust_PO = p.Cust_PO
                       AND v.Vcat > 0 )
UNION
SELECT p.Material_Code, p.Cust_PO, 0 AS VCat
  FROM Pool p
 WHERE EXISTS ( SELECT *
                  FROM VARAX v
                 WHERE v.Material_Code = p.Material_Code
                       AND v.Cust_PO = p.Cust_PO
                       AND v.Vcat = 0 )
       AND NOT EXISTS ( SELECT *
                          FROM VARAX v
                         WHERE v.Material_Code = p.Material_Code
                               AND v.Cust_PO = p.Cust_PO
                               AND v.Vcat > 0 )
UNION
SELECT p.Material_Code, p.Cust_PO, -999 AS VCat
  FROM Pool p
 WHERE NOT EXISTS ( SELECT *
                    FROM VARAX v
                   WHERE v.Material_Code = p.Material_Code
                         AND v.Cust_PO = p.Cust_PO );

【讨论】:

    【解决方案2】:

    不要直接加入 VA05(ZRAX),而是尝试加入 VA05(ZRAX) 中按您想要的方式分组的行的查询结果。您可以通过两个子查询分组来实现这一点,该子查询为带零和不带零的最小值分组。

    所以你会有另一个名为 qry_va05zrax_toPool_min 的查询

    select 
    [po number], description, 
    vcatmin:min(vcat)
    from VA05(ZRAX)
    group by 
    [po number],description
    

    和 qry_va05zrax_toPool_minGT0:

    select 
    [po number], description, 
    vcatminGT0:min(vcat)
    from VA05(ZRAX)
    group by 
    [po number],description
    having vcat > 0
    

    还有第三个类似:

    select
    [po number], description, vcatVal:iif(vcatminGT0 is not null, vcatminGT0,iif(vcatmin is not null, 0, null) )
    from
    1poolWaitingExchange p left outer join
    qry_va05zrax_toPool_min m on
    p.[po number] = m.[po number] and
    p.description = m.description left outer join
    qry_va05zrax_toPool_minGT0 z on
    p.[po number] = z.[po number] and
    p.description = z.description
    

    【讨论】:

    • 我了解这样做的方法,我也喜欢它背后的想法。但是,我在第一个查询中想要的结果不仅仅是 min(Vcat),而是说如果 Vcat 有 0、1、2,我希望结果为 1。如果 Vcat 只有 0,那么结果是 0。 Min(Vcat ) 无论如何都给出了最低记录,所以它不太符合我需要的结果
    • 尝试更新后的答案,您可以使用两个子查询来确定两个最小值,一个带零,一个不带零。
    【解决方案3】:

    听起来你想要这样的东西。不幸的是,我目前无法测试我的 Access 语法。 (我还假设“空白”实际上为空。如果不是,请澄清Vcat 的数据类型。)

    select
        pwe.[Cust PO], pwe.[Part Number],
        switch(
            not isnull(min(switch(Vcat between 1 and 3, Vcat))),
              min(switch(Vcat between 1 and 3, Vcat))
            min(Vcat) = 0, 0,  true, null
        ) as Vcat
    from
       1Poolwaitingexchange as pwe inner join VA05 as va
           on va.[PO Number] = pwe.[Cust PO] and va.Description = pwe.[Part Number]
    group by pwe.[Cust PO], pwe.[Part Number]
    

    你说得对,我的逻辑本来就很糟糕。最小的 0 总是会取代 1 到 3 之间的合法值。修改后的版本通过使用将超出该范围的值视为空值的逻辑来处理这个问题,因此它们可以被 min 聚合忽略。

    您可以使用下面略短的版本。这三个都有一个共同的英文解释:“1 和 3 之间有一个值吗?然后返回最小的那个。”我认为后两者读起来更好,但我不知道您是否会添加其他可能破坏它们的值。由于我不知道Vcats 的性质以及它们可能会如何变化,所以我将把它留给你。

        switch(
            max(Vcat) > 0, min(switch(Vcat between 1 and 3, Vcat))
            min(Vcat) = 0, 0,
            true, null
        ) as Vcat
    
        switch(
            max(Vcat) between 1 and 3, min(switch(Vcat between 1 and 3, Vcat))
            min(Vcat) = 0, 0,
            true, null
        ) as Vcat
    

    【讨论】:

    • Vcat 的数据类型是数字。当我运行此查询时,我收到以下错误:查询表达式中的语法错误(缺少运算符)'case When min(Vcat)........ else null end'。
    • 试试switch()'。不知道为什么我写这个,因为我知道 Access 不使用 case
    • 我尝试编写一个特定的查询,只是为了过滤掉我的 VA05(ZRAX) 表中使用switch() 标准的重复项,但返回给我的所有值都是 NULL。 SELECT [VA05(ZRAX)].[PO Number], [VA05(ZRAX)].Description, Switch(Min(Vcat) Between 1 And 3,Min(Vcat),Min(Vcat)=0,0,True,Null) AS Vcata FROM [VA05(ZRAX)] GROUP BY [VA05(ZRAX)].[PO Number], [VA05(ZRAX)].Description;您对为什么会出现这种情况有任何见解吗?
    • @Andrew 我不知道。但请尝试将第三个值中的 null 更改为 99 或其他内容,以了解这是否是空值的来源。
    • @Andrew 在其他结果旁边添加列 min(Vcat) 也将有助于您的调试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-11
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    • 2014-04-23
    • 2015-02-03
    • 1970-01-01
    相关资源
    最近更新 更多