Oracle SQL Count基于条件

时间:2014-08-27 20:51:58

标签: sql oracle count

我正在尝试创建一个查询来计算每个资产位置中的电缆数量。流程是Project-> Asset-> Cable。一个项目可以有多个资产,其中有多条电缆与这些资产相关联。以下是数据的快照。

RECORD_ID    PARENT_RECORD_ID    FORM_NAME    PARENT_FORM    FIELD_NAME   VALUE
   1604            1603            asset         project       serial     b345s
   1604            1603            asset         project       location   OH
   1605            1604            cable         asset         zone       green
   1606            1603            asset         project       location   NY
   1607            1606            cable         asset         port       2

如上所示,在电缆级别,PARENT_RECORD_ID是资产的“RECORD_ID”。这只是一个快照,因为有数千行,其间有一堆数据,但我试图只显示相关数据。

我需要找出一种方法来累计每个资产的电缆数量,然后按“位置”对资产进行分组。 “location”是资产的FIELD_NAME列中的值,其值与VALUE列中的值相关联。例如,上面是资产ID 1604,'location'是'OH'。

到目前为止,我已经能够计算出电缆的总数。我只需要弄清楚如何通过他们的“资产”的“位置”来打破这些。

SELECT
  COUNT(DISTINCT RECORD_ID) "Number of Cables"
FROM 
  PROJECT_TABLE
WHERE 
  LOWER(FORM_NAME) = 'cable'

上述查询的当前结果:

Number of Cables
     3137

我希望结果如下:

Location     Number of Cables
  OH                552
  NY               1042
  MI                49
  CA               1494

非常感谢任何帮助!谢谢!

1 个答案:

答案 0 :(得分:1)

这应该可以解决问题。

select
  ass.VALUE as LOCATION,
  COUNT(DISTINCT cab.RECORD_ID) as CABLE_COUNT
from
  PROJECT_TABLE cab
  inner join PROJECT_TABLE ass on ass.RECORD_ID = cab.PARENT_RECORD_ID
where
  cab.FORM_NAME = 'cable' and
  ass.FORM_NAME = 'asset' and -- should always be the case?
  ass.FIELD_NAME = 'location'
group by
  ass.VALUE

一些提示:

  • 为表使用别名。在这种情况下,你必须,因为同一个表使用了两次,但我也是在不必要的时候这样做。
  • 如果您使用别名,请确保在查询资产时使用ass之类的缩写。这是生活中的一点点乐趣。 :)
  • 我已删除lower。如果不需要,请将其删除。无需调用函数,您可以完全使用索引,您的查询将更快。确保所有值具有相同的大小写或更好,使Forms表包含具有数字ID的名称,并在其他表中使用该ID。 (Google 代理键)。或者,查看函数索引。这允许Oracle基于函数结果而不是正常值构建索引。
  • 如果只有一条电缆记录,则您在计数中不需要distinct,并且您不会需要条件ass.FORM_NAME = 'asset',因此您的查询已经过优化再多一点。
  • FORM_NAMEVALUE上的综合索引是有益的,但只要您同时需要这两个条件(请参阅查询中的评论)并且不使用lower(请参阅上面的两个评论)。
  • 一般来说,像这样的通用表是不好的做法。如果您有资产,项目和位置的单独表格,并从中制作正确的规范化模型,您将拥有更好,更易于维护的数据模型,更易于阅读和使用。