【问题标题】:How to calculate between different group of rows of the same table如何计算同一张表的不同组的行之间
【发布时间】:2013-02-21 12:55:32
【问题描述】:

有一个表:

Year   Month   Value
2011   1       500
2011   2       550
2011   3       600
...
...
2012   1       600
2012   2       750
2012   3       930

有没有办法可以计算同月/不同年份的值之间的差异,所以得到的结果是:

Month    Value
1        100
2        200
3        330
...

我试图做类似的事情:

select month, a.value-b.value
from
  (select month, value from table where year = 2012) a,
  (select month, value from table where year = 2011) b

但输出是 12 个月(选择 a (2012) * 12 个月选择 b (2011)..


编辑:抱歉缺少重要信息:

正在通过 odbc:jdbc 桥对 excel 表进行查询。

因为“from”子句总是这样:[sheet1$] 我无法创建任何连接或大小写:(

【问题讨论】:

  • 你想要的输出是什么?

标签: sql


【解决方案1】:

您非常接近如何获得结果。我建议使用与此类似的方法,将数据 pivots 到列中,然后您可以获取每年之间的差异:

select month,
  Year2012-Year2011 as Diff
from
(
  select month,
    sum(case when year = 2011 then value end) Year2011,
    sum(case when year = 2012 then value end) Year2012
  from yourtable
  group by month
) src     

SQL Fiddle with Demo

【讨论】:

  • 当他有 2013 年、2014 年等等时会发生什么。我们可以进行广义查询吗?
  • @AshReva 您可以创建一个动态查询来生成年份列表,但 OP 必须说明他们使用的是什么 RDBMS,因为每个 RDBMS 的语法都不同。
  • @AshReva 有许多不同的方式来执行这个查询。
【解决方案2】:

您的查询不起作用,因为您在表上执行CROSS JOIN(因为,),所以每一行都与另一个表中的每一行匹配,而不是INNER JOIN月。

修改您的查询:

select a.month, a.value-b.value
from
  (select month, value from table where year = 2012) a
  JOIN
  (select month, value from table where year = 2011) b
  ON a.month = b.month

更快的查询:

select a.month, a.value-b.value
from
  yourTable a
  join yourTable b
    on a.month = b.month
  where a.year = 2012 and b.year = 2011

对于每年每个月的多行:

select a.month, a.value-b.value
from
  (select month, sum(value) as value
   from yourTable where year = 2012
   group by month) a
  join
  (select month, sum(value) as value
   from yourTable where year = 2011
   group by month) b
    on a.month = b.month

SQLFiddle.

【讨论】:

    【解决方案3】:

    这样的?假设 year/month 是唯一的。

    SELECT
        a.month,
        a.value - b.value
    FROM
        tablename a
        INNER JOIN tablename b
            ON a.year - 1 = b.year
            AND a.month = b.month
    

    【讨论】:

      【解决方案4】:

      只需在您的查询中添加where 子句..

      select month, a.value-b.value
      from
        (select month, value from table where year = 2012) a,
        (select month, value from table where year = 2011) b
      where a.month = b.month
      

      您正在做的是交叉连接,将第一个表中的每一行与第二列的每一行组合在一起,其中将过滤掉与不同月份编号匹配的行。

      【讨论】:

        【解决方案5】:

        您想进行自联接。一般的想法是从同一个表中选择两次,但使用不同的别名。

        select t1.something, t2.something
        from yourtable t1 join yourtable t2 on something
        etc
        

        【讨论】:

          【解决方案6】:

          select a.month,(a.value-(select b.value from @tablename b where b.year = @year2 and b.month = a.month)) 作为 diff 来自@tablename 其中 a.year = @year1

          我想它会对你有所帮助。实际上,我们知道我们只能在减法中使用两个数字,所以在这里我使用了 year1 和 year 2。把你的表名放在正确的位置

          【讨论】:

            【解决方案7】:

            此外,如果您的示例中每月只有 2 个值,并且您的 SQL 版本中提供了分析函数,那么这将起作用。你可以对它进行不同的分区...:

            SELECT distinct month, (l_val - f_val) value
              FROM
              (
              SELECT year, month, month_val
                   , FIRST_VALUE(month_val) OVER (PARTITION BY month ORDER BY month) f_val 
                  , LAST_VALUE(month_val) OVER (PARTITION BY month ORDER BY month) l_val 
                FROM your_table
              )
             ORDER BY 1
             /
            
            MONTH    VALUE
            ----------------
            1        100
            2        200
            3        330
            

            在我个人看来,内联视图比加入更好,虽然你无论如何都会加入,但它仍然更具可读性,更易于调试......

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2017-07-17
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多