【问题标题】:Get count of distinct groups in a single SQL query in Firebird 1.5?在 Firebird 1.5 的单个 SQL 查询中获取不同组的数量?
【发布时间】:2009-08-19 19:45:55
【问题描述】:

我在存储过程中遇到了以下问题:

  for
    select 1
    from   scan_queue
    where  ( date_time_locked is null       )
      and  ( scan_seqno >= :varMinScanSeqno )
      and  ( scan_seqno <= :varMaxScanSeqno )
    group by loan_id, collateral_id, insurance_id
    into   varNotUsed
  do
    varItemsToScan = varItemsToScan + 1;

我的第一个想法是,这可能是一种计算组数的低效方式,但我的第二个想法是,“嘿,无论如何,您如何在单个查询中编写它?”我没有一个好的答案。 (所以这更像是一个学术问题。)我不是在寻找连接 ID 的解决方案,如下所示:

select count(distinct loan_id || collateral_id || insurance_id)
from   scan_queue
where  ( date_time_locked is null       )
  and  ( scan_seqno >= :varMinScanSeqno )
  and  ( scan_seqno <= :varMaxScanSeqno )

查询此信息的最佳方式是什么?

编辑:由于我显然没有说得足够清楚,所以我使用的是 Firebird v1.5。

【问题讨论】:

  • 我把 Firebird 作为一个标签,但为了澄清,我对一个与 Firebird 1.5+ RDBMS 一起工作的解决方案特别感兴趣。 :)
  • 此评论非常重要,足以成为问题的一部分!我什至不知道 Firebird 是一种 DB 类型! :)
  • @Aviad,我根据您的建议更新了问题。感谢您的评论,因为我在这里相对较新,并且认为标签就足够了(这实际上是我的第一个问题)。

标签: sql count firebird distinct


【解决方案1】:

由于您使用的是 Firebird 1.5,因此似乎没有一个干净的解决方案。

Firebird 2.0 支持“FROM 子句中的子查询”表示法,这是回答此类问题的基本要求 - 请参阅所有其他答案。

所以,如果您需要一个干净的解决方案,请升级到 Firebird 2.1。否则,您所拥有的似乎与您所能获得的一样好。

(其他一些 DBMS 支持临时表;如果 Firebird 1.5 支持,您可以将初始数据选择到临时表中,然后计算临时表中的行数,然后再次删除临时表。)

【讨论】:

  • 我们最终还是升级到了 FB 2.1。同时,我使用了问题中发布的代码。
【解决方案2】:

普通的旧 count(distinct ..) 有什么问题?

select count(*) from ( 
select loan_id, collateral_id, insurance_id
from   scan_queue
where  ( date_time_locked is null       )
  and  ( scan_seqno >= :varMinScanSeqno )
  and  ( scan_seqno <= :varMaxScanSeqno )
group by loan_id, collateral_id, insurance_id
)

【讨论】:

  • 你的 DBMS 中的 SQL 真的有效吗?
  • 它不在 Oracle 或 Access 中。也许是 SQL Server?但不管怎样,总感觉有些不对劲。希望我有我需要的东西来测试它。如果可行,在我看来应该删除 group by 子句。
  • 没有理由同时拥有同一列的 group by 和 distinct。
  • 如果您删除 group by 子句,它将在其他 DBMS 中工作,但不是 Asmodon 正在使用的那个(Firebird 1.5)。它与此处的其他答案的概念相同,但鉴于 Firebird 1.5 的局限性,我认为问题中的原始示例是最简单的解决方案(但不知道效率如何,但未经测试。)。
【解决方案3】:

不知道效率更高还是更低,但子查询可以做到。

select count(grouping) 
from
( select count(*) as grouping
    from   scan_queue
    where  ( date_time_locked is null       )
      and  ( scan_seqno >= :varMinScanSeqno )
      and  ( scan_seqno <= :varMaxScanSeqno )
    group by loan_id, collateral_id, insurance_id) a

【讨论】:

  • 感谢您的回复,但这对我不起作用。您使用的是哪个 DBMS?
  • 我正在使用 Oracle,我也在访问中测试了它。也许我误解了这个问题?如果我的子查询返回 5 行,那么我的 outquery 返回“5”。这就是你要找的东西吗?
  • 伊丽莎白,你完全理解了这个要求,但不幸的是,这个查询在 Firebird 中是无效的语法。
  • 啊!火鸟。我还没用过。不过,我很惊讶,因为它看起来很标准。所以你不能做子查询?或者你不能有一个做聚合的子查询?
  • Firebird 支持子查询但不支持派生表(至少在 v1.5 中),这是您的解决方案所使用的。 :)
【解决方案4】:

这适用于 SQL Server:

SELECT
    COUNT(*)
    FROM (SELECT
              GroupColumn
              FROM YourTable
              WHERE ...
              GROUP BY GroupColumn
         ) dt

【讨论】:

  • 我使用的是 Firebird,而不是 SQL Server。
  • 也许您可以使用 CTE 或简单视图来替换派生表
  • 感谢您的回复。您对视图的想法可能会奏效,但我不知道我是否想要创建更多元数据来支持查询。不幸的是,我在 v1.5 中没有 CTE 支持,但显然它在 v2.1 中受支持。我开始怀疑 FB v1.5 根本没有一种优雅的方式来查询这些信息。
  • 您似乎受到 FB v1.5 缺乏功能的限制,也许是时候升级到新版本了
  • 我们计划在今年更新到 FB 2.1。但是,由于升级导致的复杂性,它被一再推迟。你知道它是怎么回事。 ; )
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-06
  • 2013-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多