oracle 是否可以使用两次左联接来进行多次计算?

mefy6pfw  于 2022-11-28  发布在  Oracle
关注(0)|答案(3)|浏览(195)

我试着计算如果一个会员在一月份购物,那么在二月份再次购物的比例是多少,在三个月内再次购物的比例是多少。最终创建一个类似于所附图像的表格。
我已经尝试了下面的代码。第一个左连接工作,但当我添加第二个计算within_3months的错误:显示“FROM关键字未在预期的位置找到”(对于单独的行)。我可以两次离开连接还是必须为列执行单独的脚本?
第一个
我试过左创建一个单独的时间表并加入到这个。它不起作用。单独做计算工作,但我必须为多个时间框架这样做,所以将需要很长时间。

jv2fixgn

jv2fixgn1#

错误不是来自添加的左连接,而是来自as 1month_retention_rate部分,因为它是非法名称。
您可以通过以下方式更简单地了解这一点:

select dummy as 1month_retention_rate
from dual;

ORA-00923:在预期位置未找到FROM关键字
您可以更改列别名,使其遵循命名规则(特别是在这里,不以数字开头),或者如果确实需要该特定名称,则可以将其设置为带引号的标识符-通常不是一个好选项,但有时在查询的最终输出中也是可以的。
fiddle
所以在代码中,你只需更改新行

,  count(distinct B.members)/count(distinct A.members) *100 as 1month_retention_rate

变成了

,  count(distinct B.members)/count(distinct A.members) *100 as one_month_retention_rate

或使用带引号的标识符

,  count(distinct B.members)/count(distinct A.members) *100 as "1month_retention_rate"

fiddle-仍有错误,但现在使用ORA-00942,因为我没有您的表,而且这是在将您的模糊模式/表名更改为合法名称之后。
可能有更有效的方法来执行计算,但这是一个单独的问题...

8cdiaqws

8cdiaqws2#

我能理解你想得到:

  • 在1月访问的所有成员的计数
  • 在一月访问并在二月再次访问的所有成员的计数。
  • 在一月访问并在二月、火星和四月再次访问的所有成员的计数。

如果我的理解是正确的,那么您可以使用IF而不是LEFT JOIN来简化内部查询。请看下面的查询。假设表成员有一个ID字段:

SELECT
  mem_jan AS num_of_mems_shopped_january21,
  mem_feb AS retained_february21,
  mem_feb / mem_jan * 100 as 1month_retention_rate
  mem_3m / mem_jan * 100 as within_3months
FROM(
    SELECT
      SUM(IF(mm_jan>0,1,0) AS mem_jan,
      SUM(IF(mm_jan>0 AND mm_feb>0,1,0) AS mem_feb,
      SUM(IF(mm_jan>0 AND mm_count_3m>0,1,0) AS mem_3m
    FROM
    (
        SELECT
          t.Id,
          SUM(IF(year_month = 202101, 1,0)) AS mm_jan, /*visit for a member in Jan*/
          SUM(IF(year_month = 202102, 1,0)) AS mm_feb, /*visit for a member in Feb*/
          SUM(IF(year_month between 202102 and 202104,1,0)) AS mem_3m/*visit for a member in 3 months*/
        FROM 
          table.members t
          join table.date tm on t.dt_key = tm.date_key
        WHERE
          year_month between 202101 and 202104
        GROUP BY
          t.Id
    ) AS t1
) AS t2

这不是一个最终运行的查询,但它可以解释我的想法。

sqxo8psd

sqxo8psd3#

不要使用多个联接,计算每个成员每月的商店数,然后使用条件聚合。
在Oracle中,这将是:

SELECT 202101 AS year_month,
       COUNT(CASE WHEN cnt_202101 > 0 THEN 1 END)
         AS members_shopped_202101,
       COUNT(CASE WHEN cnt_202101 > 0 AND cnt_202102 > 0 THEN 1 END)
         AS members_retained_202102,
       COUNT(CASE WHEN cnt_202101 > 0 AND cnt_202102 > 0 THEN 1 END)
       / COUNT(CASE WHEN cnt_202101 > 0 THEN 1 END) * 100
         AS one_month_retention_rate,
       COUNT(CASE WHEN cnt_202101 > 0 AND (cnt_202102 > 0 OR cnt_202103 > 0 OR cnt_202104 > 0) THEN 1 END)
       / COUNT(CASE WHEN cnt_202101 > 0 THEN 1 END) * 100
         AS within_3months
FROM   (
  SELECT members,
         year_month
  FROM   members m
         INNER JOIN date d
         ON m.dt_key = d.date_key
)
PIVOT (
  COUNT(*)
  FOR year_month IN (
    202101 AS cnt_202101,
    202102 AS cnt_202102,
    202103 AS cnt_202103,
    202104 AS cnt_202104
  )
);

相关问题