使用内联查询逐个查询的SQL帮助

时间:2013-04-29 14:35:15

标签: sql oracle

我有这两张桌子。我想计算最后一个时间段连续发出'1'的con_id的数量。
例如:A1为2,A3为1,但A2和B1为0,因为对于下表的最新结果,它们没有连续“1”。

t_conmast

  • con_id [pk]
  • off_code
  
con_id off_code
A1     1
A2     1
B1     2
A3     1

t_readbak

  • con_id [fk]
  • 计数器
  • 备注
  • 时间戳[未在表格中显示;由系统自动插入]
con_id counter remark timestamp
A1     1      0
A1     3      1
A1     6      1
B1     1      1
B1     2      0
A2     1      0
A2     2      1
A2     3      0
A3     1      1

我尝试过但失败了(我添加了off_code只是为了获得单个办公室的结果)

select con_id, 
       count(con_id) 
from t_readbak 
where remark=1 and timestamp > (select max(timestamp) 
                                from t_readbak 
                                where remark=0 
                                group by con_id) 
and con_id in (select con_id from t_conmast where off_code=1)

预期输出

con_id count(con_id)
A1     2
A2     0 
A3     1
B1     0

4 个答案:

答案 0 :(得分:1)

这是我解决这个问题的方法。首先,计算每个con_id的倒退备注累计和。然后,第一次点击remark = 0的行时,请使用该行的值。您可以使用row_number()找到第一行。

复杂的是当你没有值为0的备注时。在这种情况下,你只需要取总数。

以下查询将此逻辑合并到SQL中:

select rb.con_id,
       (case when NumZeros = 0 then numRemarks else cumsum end) as count1
from (select rb.*,
             SUM(remark) over (partition by con_id order by counter desc) as cumsum,
             ROW_NUMBER() over (partition by con_id, remark order by counter desc) as remark_counter,
             SUM(case when remark = 0 then 1 else 0 end) as NumZeros,
             SUM(remark) over (partition by con_id) as numRemarks
      from t_readbak rb
     ) rb
where (remark_counter = 1 and remark = 0) or
      (NumZeros = 0 and remark_counter = 1)

答案 1 :(得分:1)

左连接可能有用。像这样:

select con_id, count(*) records
from t_readback t1 left join t_readback t2 using (con_id, remark)
where remark = 1
and t1.counter < t2.counter
group by con_id

答案 2 :(得分:1)

如果您的意思是只想在con_id期间每个 remark包含1次,那么您可以执行以下操作:< / p>

SELECT
  con_id,
  COUNT(CASE remark = 1 THEN 1 END) AS Remark1Count,
  COUNT(CASE remark <> 1 THEN 1 END) AS RemarkNot1Count
FROM t_conmast
INNER JOIN t_readbak ON t_conmast.con_id = t_readbak.con_id
WHERE your-timestamp-condition
GROUP BY con_id
HAVING COUNT(CASE remark <> 1 THEN 1 END) = 0

HAVING将过滤掉con_id的所有remark <> 1

答案 3 :(得分:1)

获取con_id为0的每个remark的最大时间戳。 此后,再次为每个con_id计算具有较年轻时间戳的项目。通过构造在这些记录中将remark设置为1:

    select con_id
         , count(*)
      from t_readbak master
inner join t_conmast office on (     office.off_code = 1
                                 and office.con_id   = master.con_id )
inner join (
                select con_id           con_id
                     , max(timestamp)   ts
                  from (
                            select con_id
                                 , remark
                                 , timestamp
                              from t_readbak
                             where remark = 0
                       ) noremark
              group by con_id
            ) cutoff
         on ( master.con_id = cutoff.con_id )
      where master.timestamp > cutoff.ts
   group by master.con_id
          ;

timestampmax(timestamp))替换为countermin(counter)),如果您不信任您的时间戳顺序,请更改比较运算符。