2016-04-27 4 views
0

Ich führe diese Abfrage in SQL Server und es funktioniert gut, aber wenn ich versuche, es in Oracle auszuführen, gibt es nicht die gleichen Ergebnisse.Ich brauche Hilfe bei der Umwandlung von T-SQL-Abfrage in Oracle unterstützte Abfrage

Sie können in meinem anhängenden Foto die Daten eines Kunden sehen, die den Code 1, 2,4, 8 haben, und er sollte 0,70 Wert für den Code 1,2,4 erhalten und dann für den Code 8 er haben sollte 0,75 erhalten, nach der Multiplikation sollte 0,52 als Wert zurückgegeben werden. Ich habe es in Oracle versucht, indem ich null durch nvl ersetze, aber es gab 1 statt 0.52 zurück. Bitte helfen Sie mir diese Abfrage in einer Oracle-unterstützten Abfrage zu konvertieren, die die gleichen Ergebnisse liefert.

Hier ist meine Abfrage

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

Bitte, im Interesse der Vernunft, schreiben diese Abfrage ohne diese alte Joinsyntax. Verwenden Sie die richtigen LINKEN, INNEREN oder KREUZVERBINDUNGEN, je nachdem, was für Ihre Anwendung geeignet ist. Die Joins, die Sie oben verwendet haben, sind wirklich eine schlechte Übung. –

+1

Wenn Sie 'MAX sagen (FALL WENN RM_LIVE.CRWSPECFUNC.IDCRWSPECFUNC IN (31.723) THEN 0.75 ELSE 1 ENDE)' Sie würden 1 nicht 0.75 .. Sie sicher, dass Sie die Berechnung in SQL schon herausgefunden haben? scheint, dass alle deine ELSE's 0 sein sollten – JamieD77

+0

@Rich Benner Vergiss einfach die Verbindungen usw., Alles, was ich tun muss, ist, meinen Kunden einige Punkte zu geben, basierend auf den Codes, die sie durch Multiplizieren aller Werte mit denen bekommen haben Codes. Sagen wir, wenn jemand die Codes 1,2,4 und 31 hat, dann sollte er 0,70 für 1,2,4 und 0,75 für Code 31 bekommen, also wird sein Gesamtwert 0,52 sein. – Fari

Antwort

0

Da Sie nun Noten multiplizieren, zuerst müssen wir entscheiden, was die Partitur ist, wenn nicht von Codes abgestimmt ist. Ich denke, es sollte 0 sein. Als nächstes sollten wir alle möglichen Codes in unabhängige Gruppen brechen, das heißt, die Ergebnisse hängen nicht von anderen Gruppenmitglieder ab. Hier sind sie (1,2,4) und (8). Und definieren Sie die Regel für jede Gruppe. So

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; 
+0

Ein Bezeichner wie '[ID]' ist in Oracle ungültig. –

+0

Ja, einfach [] Klammern fallen lassen. Da Bezeichner keine speziellen Symbole enthalten, können Sie Klammern auch in MS SQL einfügen. – Serg

0

Es gibt einige SQL Server Dinge in der Abfrage, die nicht Standard-SQL sind:

  1. [] um Spaltennamen - entfernen Sie sie; Sie brauchen sie hier nicht (sonst würden Sie Standard-SQL-Anführungszeichen verwenden)
  2. r = expression - für einen Alias-Namen. Ändern Sie dies in Standard-SQL-expression AS r
  3. ISNULL(expression, value) - Ändern Sie dies in Standard-SQL-COALESCE(expression, value) oder Oracle NVL(expression, value)
  4. NULLIF(expression, value) - das Sie halten können; Oracle unterstützt es auch
  5. values(),(), ... - ersetzen mit einem SELECT FROM DUAL UNION ALL subquery

Sie erhalten:

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; 

Die Berechnung ist jedoch unnötig kompliziert:

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

bedeutet, wenn es mindestens eine Übereinstimmung gibt, dann 0.70 else 0, die auf null gesetzt wird, die auf 1 gesetzt wird. Das ist also dasselbe wie

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

Also, wenn ich mich nicht täusche, das ganze calcultion wird:

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 

oder

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 

Nun, es gibt viele Möglichkeiten, dies zu schreiben.

0

Der folgende Code sollte Ihnen die Antwort geben, die Sie erwarten;

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 
0

Wenn ich verstehe, was Sie suchen (dh.für jeden der Fälle muss die ID/Name-Kombination alle angegebenen Codes haben, dann wird dies wahrscheinlich tun, was Sie wollen. Vielleicht möchten Sie eine Art von trunc/Boden/Rundenfunktion auf der val Spalte hinzufügen, wenn Sie nach der Antwort auf 2 Dezimalstellen sind, aber:

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 
Verwandte Themen