【问题标题】:Oracle - Select distinct on multiple columns where count = 1Oracle - 在 count = 1 的多个列上选择不同的
【发布时间】:2017-01-12 19:02:14
【问题描述】:

我想知道是否有人可以帮助我。我想写一个查询来标识汽车的制造商和型号,如果该特定制造商/型号组合之前没有售出,则当天仅售出 1 个

假设我有一个名为 carsSold 的表,它有 4 列:ID、制造商、型号和 dateCreated,并具有以下数据:

我想要做的只是返回在当天创建条目的制造商和型号行,并且只有 1 种类型的组合(从历史上的任何日期开始)。如果我的数据集中的 currentDate 是 08-08-2016,我希望看到 id 的 1、2、4 和 7。

有可能做到这一切吗?从 select 语句中可以实现很多目标。我认为它会开始类似于下面的内容,只是它将包含两行制造商和型号的不同和计数或类似的东西?我只是不确定如何实现我所需要的。

 select * 
 from carsSold
 where dateCreated > trunc(sysdate)

提前感谢您抽出宝贵时间查看此内容以及我可能获得的任何帮助。

【问题讨论】:

  • 这还不清楚。您是在过去某个日期(例如 08-08-2016)运行此“截止日期”,还是在当天(今天)运行此“截止日期”?如果您想在过去的某个日期运行它,也许您将在运行查询时输入它,那么不应该引用“当前”或sysdate。我很困惑。
  • @mathguy 我的解决方案不关心它是否在当前日期运行。假设它可以在任何日期运行更安全。但是,是的,我知道“所有日期”与“某个日期之前的所有日期”之间的区别。
  • @shawnt - 这是不正确的。除了需要在您的解决方案中将sysdate 更改为“一些”输入日期(这并不困难)之外,您还需要进行一些其他更改 - 如果表中有 LATER 条目,count() 条件可能会失败。 (也不难,例如使用 where 子句 - 但对于更一般的问题,您的解决方案原样不起作用。)
  • @mathguy 我知道你来自哪里,我之前不得不向人们解释过。我确实尝试编写无论以后要添加的数据如何都可以工作的查询,并澄清这一点。这次似乎更容易回答提出的问题。

标签: sql oracle oracle11g


【解决方案1】:
select min(Id), Manufacturer, Model, min(dateCreated)
from carsSold
group by Manufacturer, Model
having count(*) = 1 and min(dateCreated) = trunc(sysdate);

这是一个非常标准的group by 查询。 having 保证我们只得到单行的组。针对dateCreated 的条件必须使用聚合,但由于组中只有一行,所以min() 确实是一回事。

释义:返回所有组,其中制造商和型号的组合被计算一次,其中最早的日期是当天(或您选择的任何日期)。id 和创建日期值作为虚拟聚合恢复。

编辑:我很清楚您不打算追溯运行此查询,并且您只会对使用当天的日期感兴趣。所以我觉得没有必要早点发表这个评论。但是,如果您确实需要及时回顾,那么添加where dateCreated <= <some date> 并在having 子句中替换相同的日期是非常简单的,这样以后创建的所有行都不会被考虑。

编辑 2:要简单地获取每个组合的最早行,您可以使用 not exists。实际上有多种方法可以表达这个查询,但这里有一个简单的方法。真的和上面的查询一点关系都没有。

select * from carsSold c
where not exists (
    select 1 from carsSold c2
    where
            c2.Manufacturer = c.Manufacturer
        and c2.Model = c.Model
        and c2.dateCreated < c.dateCreated
)

【讨论】:

  • 感谢 shawnt00 的精彩回答和详细解释,非常感谢。我还有一个问题。如果我想稍微更改查询,以便我只关心是否在当天购买了第一个制造商/型号组合,那么我所要做的就是从查询中删除有 count(*) = 1 吗?所以它只会有 min(dateCreated) = trunc(sysdate);即,我想检索当天购买了 FIRST 模型/制造商的所有记录,即使当天晚些时候购买了更多相同的组合。
  • 所以在我上面的数据集中,如果 08-08-2016 是当前日期,我还会看到返回的 id 9 或 10(取决于时间戳和之前插入的时间戳,我将使用 >trunc (sysdate) 而不是 =trunc(sysdate),因为我们现在谈论的是时间戳),虽然有两个第一个是在当前日期购买的。
  • @user3781095 基本上是的。此时唯一的潜在障碍是假设min(Id) 对应于作为最早时间戳的行。请参阅上面的编辑。
  • 非常好,再次感谢您的意见 :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-31
  • 2020-05-27
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多