SQL和2不同的列由不同的condtion然后减法和添加

时间:2013-11-06 17:31:03

标签: sql oracle oracle11g timestamp where-clause

我所尝试的有点复杂,我会尽力解释。

我实现了第一部分,即按小时对列进行求和。

示例

ID         TIMESTAMP          CUSTAFFECTED
1     10-01-2013 01:00:23       23
2     10-01-2013 03:00:23       55
3     10-01-2013 05:00:23       2369
4     10-01-2013 04:00:23       12
5     10-01-2013 01:00:23       1
6     10-01-2013 12:00:23       99
7     10-01-2013 01:00:23       22
8     10-01-2013 02:00:23       3

输出

      Hour          TotalCALLS   CUSTAFFECTED
  10/1/2013 01:00       3         46        
  10/1/2013 02:00       1         3
  10/1/2013 03:00       1         55
  10/1/2013 04:00       1         12
  10/1/2013 05:00       1         2369
  10/1/2013 12:00       1         99

查询

    SELECT   TRUNC(STARTDATETIME, 'HH24') AS hour, 
           COUNT(*) AS TotalCalls,
           sum(CUSTAFFECTED) AS CUSTAFFECTED
    FROM     some_table
    where STARTDATETIME >= To_Date('09-12-2013 00:00:00','MM-DD-YYYY HH24:MI:SS') and
          STARTDATETIME <= To_Date('09-13-2013 00:00:00','MM-DD-YYYY HH24:MI:SS') and
GROUP BY TRUNC(STARTDATETIME, 'HH')

我需要什么 我需要的是2个查询和按时间戳/小时分组。第二个查询与第一个查询完全相同,但只是where子句不同。

第二次查询

SELECT   TRUNC(RESTOREDDATETIME , 'HH24') AS hour, 
     COUNT(*) AS TotalCalls, 
     SUM(CUSTAFFECTED) AS CUSTRESTORED
FROM     some_table
where RESTOREDDATETIME >= To_Date('09-12-2013 00:00:00','MM-DD-YYYY HH24:MI:SS') and
      RESTOREDDATETIME <= To_Date('09-13-2013 00:00:00','MM-DD-YYYY HH24:MI:SS') 
GROUP BY TRUNC(RESTOREDDATETIME , 'HH24')

所以我需要减去custaffected - custrestoed,并显示总数。

我添加了excel文件的链接。 http://goo.gl/ioo9hg

由于

2 个答案:

答案 0 :(得分:0)

好的,现在正确的sql是问题文本,试试这个:

SELECT TRUNC(STARTDATETIME, 'HH24') AS hour,        
   COUNT(*) AS TotalCalls, 
   Sum(case when RESTOREDDATETIME is null Then 0 else 1 end) RestoredCount,
   Sum(CUSTAFFECTED) as CUSTAFFECTED,
   Sum(case when RESTOREDDATETIME is null Then 0 else CUSTAFFECTED end) CustRestored,
   SUM(CUSTAFFECTED) - 
    Sum(case when RESTOREDDATETIME is null Then 0 else CUSTAFFECTED end) AS CUSTNotRestored
FROM     some_table
where STARTDATETIME >= To_Date('09-12-2013 00:00:00','MM-DD-YYYY HH24:MI:SS') 
   and STARTDATETIME <= To_Date('09-13-2013 00:00:00','MM-DD-YYYY HH24:MI:SS') 
GROUP BY TRUNC(STARTDATETIME, 'HH24')

答案 1 :(得分:0)

我最近需要这样做,并且必须使用它来使它工作。

挑战在于将一个查询的结果链接到同一查询内的另一个查询,然后操纵字段的返回值,以便在一个查询的结果集中给定字段中的值,将其称为FieldA,从不同结果集中的字段中的值中减去,称之为FieldB。主题值是否是COUNT(...)等聚合函数的结果并不重要;它们可以是需要分组的结果集中的任何数字字段。查看聚合函数的值只意味着您需要调整查询逻辑以使用GROUP BY来获取正确的字段。该方法需要在查询中创建内联视图,并将其用作进行减法的数据源。

处理此类事情时的红鲱鱼是MINUS运算符(假设您使用的是Oracle数据库),但这不起作用,因为MINUS不是要相互减去结果集的字段值中的值,而是减去一个从查询返回的最终结果集中的另一组记录中找到的匹配记录集。此外,MINUS不是SQL标准运算符,因此如果您使用的不是Oracle,则数据库可能不支持它。不过,当你需要时,可以随心所欲。

好的,足够的前奏。这是您想要使用的查询表单,例如我们希望按YYYY-MM分组的日期范围:

select inlineview1.year_mon, (inlineview1.CNT - inlineview2.CNT) as finalcnt from
 (SELECT TO_CHAR(*date_field*, 'YYYY-MM') AS year_mon, count(*any_field_name*) as CNT
  FROM *schemaname.tablename*
   WHERE *date_field* > TO_DATE('*{a year}-{a month}-{a day}*', 'YYYY-MM-DD') and
    *date_field* < TO_DATE('*{a year}-{a month}-{a day}*', 'YYYY-MM-DD') and 
    *another_field* = *{value_of_some_kind}* -- ... etc. ...
  GROUP BY TO_CHAR(*date_field*, 'YYYY-MM')) inlineview1,
 (SELECT TO_CHAR(*date_field*, 'YYYY-MM') AS year_mon, count(*any_field_name*) as CNT
  FROM *schemaname.tablename* 
   WHERE *date_field* > TO_DATE('*{a year}-{a month}-{a day}*', 'YYYY-MM-DD') and
     *date_field* < TO_DATE('*{a year}-{a month}-{a day}*', 'YYYY-MM-DD') and
     *another_field* = *{value_of_some_kind}* -- ... etc. ...
  GROUP BY TO_CHAR(*date_field*, 'YYYY-MM')) inlineview2
WHERE
inlineview1.year_mon = inlineview2.year_mon
order by *either or any of the final resultset's fields* -- optional

有点抽象,一个书商希望看到2013年任何一个月内出售的书籍净数量的例子。为此,卖家必须从销售的数量中减去重新退款的书籍数量。 。他并不关心这本书何时被出售,因为他认为退回的书籍无论出现何时出售,都会在统计上显示出销售和收入的损失。例如:

select bookssold.year_mon, (bookssold.CNT - booksreturned.CNT) as netsalescount from
 (SELECT TO_CHAR(SALE_DATE, 'YYYY-MM') AS year_mon, count(TITLE) as CNT
  FROM RETAILOPS.ACTIVITY
   WHERE SALE_DATE > TO_DATE('2012-12-31', 'YYYY-MM-DD') and
    SALE_DATE < TO_DATE('2014-01-01', 'YYYY-MM-DD') and 
    OPERATION = 'sale'
  GROUP BY TO_CHAR(SALE_DATE, 'YYYY-MM')) bookssold,
 (SELECT TO_CHAR(SALE_DATE, 'YYYY-MM') AS year_mon, count(TITLE) as CNT
  FROM RETAILOPS.ACTIVITY
   WHERE SALE_DATE > TO_DATE('2012-12-31', 'YYYY-MM-DD') and
    SALE_DATE < TO_DATE('2014-01-01', 'YYYY-MM-DD') and 
    OPERATION = 'return'
  GROUP BY TO_CHAR(SALE_DATE, 'YYYY-MM')) booksreturned
WHERE
bookssold.year_mon = booksreturned.year_mon
order by bookssold.year_mon desc

请注意,为了确保查询按预期返回,必须基于某些条件如上所示基于两个内联视图,如:

bookssold.year_mon = booksreturned.year_mon

或计算记录的减法不能以1:1为基础进行,因为查询解析器将不知道从中减去哪些带有分组计数值的记录。未指定等值连接条件将产生笛卡尔连接结果,可能不是您想要的(尽管您可能想要这样)。例如,在'bookssold.year_mon'之后添加'booksreturned.year_mon'到上面示例中顶级选择语句中的返回字段列表并删除

bookssold.year_mon = booksreturned.year_mon
WHERE子句中的

条件将生成一个工作查询,该查询对结果集前两列中YYYY-MM值的CNT值进行减法计算,并在第三列中显示它们。如果您需要,可以随时了解这一点,因为它可以在业务趋势分析中具有可靠的应用,如果您可以比较销售和退货,不仅仅是在给定的原子时间范围内,而是以1:N的方式比较这些时间范围。