我需要帮助将T-SQL查询转换为Oracle支持的查询

时间:2016-04-27 15:48:15

标签: sql sql-server oracle tsql

我在SQL Server中执行此查询并且它工作正常但是当我尝试在Oracle中执行它时,它没有给出相同的结果。

你可以在我附带的照片中看到一个客户的数据,它有代码1,2,4,8,他应该得到0.70值代码1,2,4然后代码为8他应该得到0.75所以在乘法后它应该返回0.52作为值。我在Oracle中通过nvl替换为null来尝试它,但它返回1而不是0.52。请帮助我在oracle支持的查询中转换此查询,该查询将返回相同的结果。

这是我的查询

 SELECT [id] ,[name],r = isnull(nullif(
    max(CASE WHEN [code]  IN (1,2,4) then 0.70 else 0 end)
  ,0),1)
* isnull(nullif(
   min(CASE WHEN [code]  IN (1,2) then 0 else 1 end) 
    * max(CASE WHEN [code]  IN (4) then 0.20 else 0 end)
  ,0),1)
* isnull(nullif(
    max(CASE WHEN [code] IN (8) then 0.75 else 0 end)
  ,0),1)
  FROM  (values (1, 'ali',4)
        ,(1, 'ali',1)
        ,(1, 'ali',8)
        ,(1, 'ali',2)
        ,(2, 'sunny',1)
     ,(4, 'arslan',4)) as t(id, name,code)
  GROUP BY id, name;

4 个答案:

答案 0 :(得分:0)

由于你现在正在增加得分,首先我们需要决定,如果不匹配代码,得分是多少。我想,它应该是0。 接下来,我们应该将所有可能的代码分成独立的组,即哪些结果不依赖于其他组成员。这里是(1,2,4)和(8)。并为每个组定义规则。 所以

SELECT [id] ,[name],r = 
  -- At least one of values needed to get score > 0
  MAX(CASE WHEN code IN (1,2,4, 8) THEN 1.0  ELSE 0.0 END) *
  -- Now rules for every independent set of codes. Rule should return score if matched or 1.0 if not matched
  -- (1,2,4)
  coalesce(MAX(CASE WHEN [code] IN (1,2,4) THEN 0.70 END), 1.0 ) *
  -- (8) 
  coalesce(MAX(CASE WHEN [code] IN (8) THEN 0.75 END), 1.0)
  -- more ?
  FROM  (values (1, 'ali',4)
        ,(1, 'ali',1)
        ,(1, 'ali',8)
        ,(1, 'ali',2)
        ,(2, 'sunny',1)
     ,(4, 'arslan',4)) as t(id, name,code)
  GROUP BY id, name;

答案 1 :(得分:0)

查询中有一些SQL Server的东西不是标准的SQL:

    列名称周围的
  1. [] - 删除它们;你在这里不需要它们(否则你会使用标准的SQL引号"")
  2. r = expression - 代表别名。将其更改为标准SQL expression AS r
  3. ISNULL(expression, value) - 将其更改为标准SQL COALESCE(expression, value)或Oracle NVL(expression, value)
  4. NULLIF(expression, value) - 你可以保留; Oracle也支持它
  5. values (), (), ... - 替换为SELECT FROM DUAL UNION ALL子查询
  6. 你得到:

    select 
      id,
      name, 
      coalesce(nullif( max(case when code in (1,2,4) then 0.70 else 0 end), 0), 1) *
      coalesce(nullif( min(case when code in (1,2) then 0 else 1 end) *
                       max(case when code in (4) then 0.20 else 0 end) , 0), 1) *
      coalesce(nullif( max(case when code in (8) then 0.75 else 0 end), 0), 1) as r
    from 
    (
      select 1 as id, 'ali' as name, 4 as code from dual
      union all
      select 1 as id, 'ali' as name, 8 as code from dual
      union all
      select 1 as id, 'ali' as name, 2 as code from dual
      union all
      select 2 as id, 'sunny' as name, 1 as code from dual
      union all
      select 4 as id, 'arslan' as name, 4 as code from dual
    )
    group by id, name;
    

    然而,计算不必要地复杂化:

    coalesce(nullif( max(case when code in (1,2,4) then 0.70 else 0 end), 0), 1)
    

    表示如果至少有一个匹配,则0.70否则0变为null,变为1.所以它与

    相同
    min(case when code in (1,2,4) then 0.70 else 1 end)
    

    所以,如果我没有弄错的话,整个计算就变成了:

    case when max(case when code in (1,2) then 1 end) = 1 
      then 0.7 else max(case when code = 4 then 0.14 else 1 end) end *
    min(case when code = 8 then 0.75 else 1 end) as r
    

    case when max(case when code in (1,2) then 1 end) = 1 then 0.7 
         when max(case when code = 4 then 1 end) = 1 then 0.14 
         else 1 
    end *
    min(case when code = 8 then 0.75 else 1 end) as r
    

    嗯,有很多方法可以写这个。

答案 2 :(得分:0)

以下代码应该为您提供您期望的答案;

CREATE TABLE #TestData (ID int, Name varchar(10), Code int)
INSERT INTO #TestData (ID, Name, Code)
VALUES
(1,'ali',4)
,(1,'ali',1)
,(1,'ali',8)
,(1,'ali',2)
,(2,'sunny',1)
,(4,'arslan',4)

SELECT DISTINCT
     a.id
    ,a.Name
    ,COALESCE(b.HasCode1, b.HasCode2, b.HasCode4,1) * COALESCE(b.HasCode8,1) Result

FROM (SELECT ID, Name FROM #TestData GROUP BY ID, Name) a
LEFT JOIN
(
SELECT
ID
,Name
,SUM(CASE WHEN CODE = 1 THEN 0.7 END) HasCode1
,SUM(CASE WHEN CODE = 2 THEN 0.7 END) HasCode2
,SUM(CASE WHEN CODE = 4 THEN 0.7 END) HasCode4
,SUM(CASE WHEN CODE = 8 THEN 0.75 END) HasCode8
FROM #TestData
GROUP BY
ID
,Name
) b
ON a.ID = b.ID
AND a.Name = b.Name

DROP TABLE #TestData

答案 3 :(得分:0)

如果我了解你之后的情况(即,对于每种情况,id / name组合需要指定所有代码),那么这可能会完成你之后的工作。你可能想在val列上添加某种trunc / floor / round函数,如果你在2位小数的答案之后,但是:

with t as (select 1 id, 'ali' name, 4 code from dual union all
           select 1 id, 'ali' name, 1 code from dual union all
           select 1 id, 'ali' name, 8 code from dual union all
           select 1 id, 'ali' name, 2 code from dual union all
           select 2 id, 'ali' name, 4 code from dual union all
           select 2 id, 'ali' name, 8 code from dual union all
           select 3 id, 'bob' name, 1 code from dual union all
           select 3 id, 'bob' name, 2 code from dual union all
           select 3 id, 'bob' name, 8 code from dual),
   res as (select id,
                  name,
                  case when count(distinct case when code in (1, 2, 4) then code end) = 3 then 0.7 
                       when count(distinct case when code in (1, 2) then code end) = 2 then 0.5
                       else 1
                  end case_1_2_and_poss_4,
                  case when count(distinct case when code = 8 then code end) = 1 then 0.75 else 1 end case_8
           from   t
           group by id, name)
select id,
       name,
       case_1_2_and_poss_4 * case_8 val
from   res;

        ID NAME        VAL
---------- ---- ----------
         1 ali       0.525
         2 ali        0.75
         3 bob       0.375