【问题标题】:Aggregation + Rank in SPARQL -> Cumulative Percent?SPARQL 中的聚合 + 排名 -> 累积百分比?
【发布时间】:2013-12-05 04:17:24
【问题描述】:

Joshua Taylor 在回答以下问题时提出了一种非常优雅的计算 SPARQL 排名的方法 How to rank values in SPARQL?

但是,我需要聚合 + 排名作为第一步,以获取“占销售额前 50% 的国家/地区”等查询的累积百分比。

假设我们在州一级有销售

California 30
Arizona 25
...
Alberta 25
Quebec 20
...

我需要先按国家汇总并获得国家的排名如下

United States 250 1
Canada 200 2
Mexico 150 3
...

如何在 SPARQL 中编写 Aggregation + Rank 来概括上面提到的 Joshua 的答案?

对于下一步,我需要使用以下排名进行累积总和

United States 250 1 250
Canada 200 2 450
Mexico 150 3 600
...

为了用 SPARQL 编写这个,我想我可以使用这里报告的 SQL 技巧 how to get cumulative sum

如果以上都成功了,那么我们可以试试累计百分比。现在假设所有国家/地区的总销售额为 1000。那么结果将是

United States 250  250
Canada 200 450

为了在 SPARQL 中编写这个,我们可以使用 SQL 中类似的东西

SELECT CountryName, SalesAmount
FROM CumSalesCountry
WHERE CumSalesAmount <=
(SELECT MIN(CumSalesAmount) FROM CumSalesCountry
WHERE CumSalesAmount >=
(SELECT 0.5 * SUM(SalesAmount) FROM SalesCountry) ) )

对此的任何帮助将不胜感激

Esteban(努力在 SPARQL 中编写类似 BI 的查询...)

【问题讨论】:

    标签: sparql aggregation rank


    【解决方案1】:

    假设你有这样的数据:

    @prefix : <urn:ex:> .
    
    :a1 a :A ; :v 05 .
    :a2 a :A ; :v 10 .
    
    :b1 a :B ; :v 10 .
    :b2 a :B ; :v 10 .
    :b3 a :B ; :v 05 .
    
    :c1 a :C ; :v 10 .
    

    然后你可以使用这样的查询:

    prefix : <urn:ex:>
    
    select
       ?type
       (?value*100/?total as ?percent)
       (count(?type2) as ?rank)
       (sum(?value2)*100/?total as ?cumulativePercent)
    where { 
      #-- total value across all types 
      { select (sum(?value) as ?total) 
        where { ?x :v ?value } }
    
      #-- each type and its sum value as ?type and ?value
      { select ?type (sum(?v) as ?value)
        where { ?x a ?type ; :v ?v }
        group by ?type }
    
      #-- each type and its sum value as ?type2 and ?value2
      { select ?type2 (sum(?v) as ?value2)
        where { ?x a ?type2 ; :v ?v }
        group by ?type2 }
    
      filter ( ?value2 >= ?value )
    }
    group by ?type ?value ?total
    order by desc(?percent)
    

    要得到这样的结果:

    ---------------------------------------------
    | type | percent | rank | cumulativePercent |
    =============================================
    | :B   | 50.0    | 1    | 50.0              |
    | :A   | 30.0    | 2    | 80.0              |
    | :C   | 20.0    | 3    | 100.0             |
    ---------------------------------------------
    

    现在,这里有一个问题,如果两个类型有相同的 百分比。例如,如果您添加数据

    :d1 a :D ; :v 07 .
    :d2 a :D ; :v 08 .
    

    然后你得到结果:

    ---------------------------------------------------------------------------
    | type | percent                     | rank | cumulativePercent           |
    ===========================================================================
    | :B   | 38.461538461538461538461538 | 1    | 38.461538461538461538461538 |
    | :A   | 23.076923076923076923076923 | 3    | 84.615384615384615384615384 |
    | :D   | 23.076923076923076923076923 | 3    | 84.615384615384615384615384 |
    | :C   | 15.384615384615384615384615 | 4    | 99.999999999999999999999999 |
    ---------------------------------------------------------------------------
    

    这表明 A 和 D 是并列的,并且给它们相同的累积 百分比和排名。如果这不是你想要的,你可以添加 过滤条件的一些东西,例如,

    filter (  ?value2 > ?value
           || ( ?value2 = ?value &&
                str(?type2) >= str(?type) ))
    

    解决相同的情况并获得如下结果:

    ---------------------------------------------------------------------------
    | type | percent                     | rank | cumulativePercent           |
    ===========================================================================
    | :B   | 38.461538461538461538461538 | 1    | 38.461538461538461538461538 |
    | :D   | 23.076923076923076923076923 | 2    | 61.538461538461538461538461 |
    | :A   | 23.076923076923076923076923 | 3    | 84.615384615384615384615384 |
    | :C   | 15.384615384615384615384615 | 4    | 99.999999999999999999999999 |
    ---------------------------------------------------------------------------
    

    【讨论】:

      【解决方案2】:

      SPARQL 支持子查询,这些子查询可用于作为整体查询的一部分计算聚合:

      SELECT * {
        { SELECT (MIN(?CumSalesAmount) AS ?minSalesAmount) 
          {  ... get ?CumSalesAmount ... } }
        { SELECT (0.5*sum(?SalesAmount) AS ?aggSalesAmount) 
           {  ... get ?SalesAmount ... } }
        ... get ?CountryName ?SalesAmount ...
      }
      

      效果并不相同 - 这是解决问题的一种方式,而不是您示例的翻译克隆。

      【讨论】:

        猜你喜欢
        • 2018-09-08
        • 1970-01-01
        • 1970-01-01
        • 2017-03-03
        • 1970-01-01
        • 1970-01-01
        • 2019-03-25
        • 2021-03-08
        • 1970-01-01
        相关资源
        最近更新 更多