1

我正在尝试将上述脚本从 MySQL 转换为 ORACLE,而我完全是使用 ORACLE 数据库和 PL/SQL 的初学者。我读到 MYSQL 中的 IFNULL 相当于 ORACLE 中的 NVL,但我仍然无法转换超出脚本。请帮忙。

SET @r:=0;

CREATE TABLE COUNTRY_MONDIAL AS 
SELECT @r:=@r+1 RowN, @Dtf0:=Dtf0 Dtf0, @Dtf1:=Dtf1 Dtf1, 
IFNULL((log(log(@Dtf0)+1)+1),0)*9.531408863445597 + 
IFNULL((log(log(@Dtf1)+1)+1),0)*9.531408863445696 Score, Id,ID_CITY, Id, dl 
FROM (SELECT PKey, MAX(CASE WHEN WordId=205 THEN Count ELSE 0 END) AS Dtf0, 
MAX(CASE WHEN WordId=223 THEN Count ELSE 0 END) AS Dtf1 
FROM COUNTRY_I WHERE WordId in (205,223) 
GROUP BY PKey HAVING Dtf0>0 OR Dtf1>0) Cnt, COUNTRY T1 
WHERE Cnt.PKey = Id
ORDER BY Score DESC;

提前致谢。

4

2 回答 2

0

在我看来,变量@r 被用来创建一个序列号,在Oracle 中可以用一个序列替换。尝试以下操作:

CREATE SEQUENCE COUNTRY_MONDIAL_SEQ
  MINVALUE 1
  NOMAXVALUE 
  NOCACHE;

CREATE TABLE COUNTRY_MONDIAL AS
  SELECT COUNTRY_MONDAIL_SEQ.NEXTVAL AS ROWN,
         cnt.DTF0,
         cnt.DTF1,
         NVL(LOG(LOG(cnt.DTF0)+1)+1, 0) * 9.531408863445597 +
           NVL(LOG(LOG(cnt.DTF1)+1)+1, 0) *9 .531408863445696 AS SCORE,
         t1.ID,
         t1.ID_CITY,
         t1.ID,
         t1.DL
    FROM (SELECT PKEY,
                 MAX(CASE WHEN WORDID = 205 THEN COUNT ELSE 0 END) AS DTF0,
                 MAX(CASE WHEN WORDID = 223 THEN COUNT ELSE 0 END) AS DTF1,
            FROM COUNTRY_I
            WHERE WORDID IN (205, 223)
            GROUP BY PKEY
            HAVING DTF0 > 0 OR
                   DTF1 > 0) cnt
     INNER JOIN COUNTRY t1
       ON (t1.ID = cnt.PKEY)
     ORDER BY SCORE DESC;

分享和享受。

于 2013-08-08T17:09:29.763 回答
0

这是我想出的(尚未测试)

CREATE TABLE COUNTRY_MONDIAL 
AS 
SELECT ROW_NUMBER() OVER (ORDER BY t.Score DESC) AS RowN
     , c.Dtf0
     , c.Dtf1
     , COALESCE((LOG(LOG(c.Dtf0)+1)+1),0)*9.531408863445597 
       + COALESCE((LOG(LOG(c.Dtf1)+1)+1), 0)*9.531408863445696 AS Score
     , t.Id
     , t.ID_CITY
     , t.Id AS Id2
     , t.dl
  FROM ( SELECT i.PKey
              , MAX(CASE WHEN i.WordId=205 THEN i.COUNT ELSE 0 END) AS Dtf0
              , MAX(CASE WHEN i.WordId=223 THEN i.COUNT ELSE 0 END) AS Dtf1
           FROM COUNTRY_I i
          WHERE i.WordId IN (205,223)
          GROUP
             BY i.PKey
         HAVING 0 < MAX(CASE WHEN i.WordId=205 THEN i.COUNT ELSE 0 END)
             OR 0 < MAX(CASE WHEN i.WordId=223 THEN i.COUNT ELSE 0 END)
       ) c
  JOIN COUNTRY t
    ON t.Id = c.PKey
 ORDER
    BY t.Score DESC;

一些注意事项:

我不相信您可以引用分配给 HAVING 子句中表达式的别名。(这可能已经改变,现在在更新的 Oracle 版本中被允许,但是在 HAVING 子句中,我们不得不重复这个表达式。

可以在 ORDER BY 子句中引用别名(UNION/UNION ALL 查询除外);我们

我们总是可以在 SELECT 列表中按列位置进行引用。

我不确定我们是否可以在 ROW_NUMBER() OVER() 中引用 ORDER BY 子句中的列别名。上面的查询做到了这一点,但重复该表达式将是解决方法。

使用表别名限定所有列引用是一种很好的做法。

Id我们不能在一个表中有两个同名的列(从生成一个指定的名称。)

NVL()在上面的查询中,COALESCE 函数执行与CASE 表达式相同的职责。(我相信 COALESCE 是更便携和 SQL-92 兼容的选项。)

我认为 COUNT 是一个关键字,用表别名 ( i.COUNT) 对其进行限定使其明确。

于 2013-08-08T17:36:46.590 回答