SQL查询可查找范围之间的日期,并从另一个查询中获取值并对其进行迭代范围?

时间:2018-09-07 21:00:09

标签: sql oracle

很抱歉,这个问题的措辞很奇怪。不确定如何措辞,但这是上下文:

我正在开发一个应用程序,该应用程序显示一些有关用户从我的Web服务器发出请求时使用单个应用程序的频率的数据。我们获取数据的方式是每次加载起始页时,都会在加载之日递增一个名为WEB_TRACKING的数据表。因此,数据中存在很多漏洞,例如,某个应用程序可能在9月1日被大量使用,而在9月2日则没有使用。我想做的是添加命中值为0的孔。这就是我想出的。

Select HIT_DATA.DATE_ACCESSED, HIT_DATA.APP_ID, HIT_DATA.NAME, WORKDAYS.BENCH_DAYS, NVL(HIT_DATA.HITS, 0) from (
    select DISTINCT( TO_CHAR(WEB.ACCESS_TIME, 'MM/DD/YYYY')) as BENCH_DAYS 
    FROM WEB_TRACKING WEB        
) workDays
LEFT join (
    SELECT TO_CHAR(WEB.ACCESS_TIME, 'MM/DD/YYYY') as DATE_ACCESSED, APP.APP_ID, APP.NAME,
    COUNT(WEB.IP_ADDRESS) AS HITS
    FROM WEB_TRACKING WEB
    INNER JOIN WEB_APP APP ON WEB.APP_ID = APP.APP_ID
    WHERE APP.IS_ENABLED = 1  AND (APP.APP_ID = 1 OR APP.APP_ID = 2)
        AND (WEB.ACCESS_TIME > TO_DATE('08/04/2018', 'MM/DD/YYYY') 
        AND WEB.ACCESS_TIME < TO_DATE('09/04/2018', 'MM/DD/YYYY')) 
    GROUP BY TO_CHAR(WEB.ACCESS_TIME, 'MM/DD/YYYY'), APP.APP_ID, APP.NAME
    ORDER BY TO_CHAR(WEB.ACCESS_TIME, 'MM/DD/YYYY'), app_id DESC
) HIT_DATA ON HIT_DATA.DATE_ACCESSED = WORKDAYS.BENCH_DAYS
ORDER BY WORKDAYS.BENCH_DAYS

它返回日期范围之间的所有日期,甚至将空匹配数转换为0。但是,它为应用程序ID和应用程序名称返回空值。这很有意义,而且我了解如何为1个应用程序提供默认值。我希望有人可以帮助我弄清楚如何针对多个应用程序进行操作。

基本上,我得到了(在仅使用一个应用程序的情况下):

   | APP_ID | NAME       | BENCH_DAYS | HITS |
   | ------ | ---------- | ---------- | ---- |
   |  NULL  | NULL       | 08/04/2018 | 0    |
   |  1     | test_app   | 08/05/2018 | 1    |
   |  NULL  | NULL       | 08/06/2018 | 0    |

但是我想要这个(有多个应用程序):

   | APP_ID | NAME       | BENCH_DAYS | HITS |
   | ------ | ---------- | ---------- | ---- |
   |  1     | test_app   | 08/04/2018 | 0    |<- these 0's are converted from null
   |  1     | test_app   | 08/05/2018 | 1    |
   |  1     | test_app   | 08/06/2018 | 0    | <- these 0's are converted from null
   |  2     | prod_app   | 08/04/2018 | 2    |
   |  2     | prod_app   | 08/05/2018 | 0    | <- these 0's are converted from null

因此,在此长篇文章中再次重申该问题。我应该如何填充此查询,以便它可以填补日期中的漏洞,而且还可以重用应用程序名称和ID并填充该信息?

1 个答案:

答案 0 :(得分:1)

您需要一个日期列表,该列表可能来自数字生成器而不是表格(如果该表格有孔,您的报告也将如此)

例如,过去30天的每个日期:

select trunc(sysdate-30) + level as bench_days from dual connect by level < 30

使用TRUNC而不是将日期转换为字符串以缩短时间

现在您有了日期列表,要添加重复的应用程序ID和名称:

select * from

    (select trunc(sysdate-30) + level as bench_days from dual connect by level < 30) dat
    CROSS JOIN
    (select app_id, name from WEB_APP WHERE APP.IS_ENABLED = 1 AND APP_ID in (1, 2) app

现在,您可以将所有日期与所有应用程序交叉使用。 2个应用程序和30天的时间将通过交叉联接产生60行结果集。左加入您的统计数据,然后分组/计数/求和/汇总...

select app.app_id, app.name, dat.artificialday, COALESCE(stat.ct, 0) as hits from

    (select trunc(sysdate-30) + level as artificialday from dual connect by level < 30) dat
    CROSS JOIN
    (select app_id, name from WEB_APP WHERE APP.IS_ENABLED = 1 AND APP_ID in (1, 2) app
    LEFT JOIN
    (SELECT app_id, trunc(access_time) accdate, count(ip_address) ct from web_tracking group by app_id, trunc(access_time)) stat
    ON
      stat.app_id = app.app_id AND
      stat.accdate = dat.artificialday

您不必以这种方式编写查询/将您的分组作为子查询进行操作,我只是以这种方式表示它,以使您考虑以块为单位的数据,您可以独立构建并稍后再连接在一起,以建立更全面的区块