2013-02-26 6 views
81

Ich brauche aus einer Tabelle auswählen Daten zu tun, basierend auf eine Art Priorität wie folgt:Können Sie wenn-dann-sonst Logik in SQL haben?

select product, price from table1 where project = 1 

-- pseudo: if no price found, do this: 
select product, price from table1 where customer = 2 

-- pseudo: if still no price found, do this: 
select product, price from table1 where company = 3 

Das heißt, wenn ich 3 Produkte mit Preisen auf project = X Basis gefunden, ich will nicht auf customer = Y auswählen . Ich möchte nur die resultierenden 3 Zeilen zurückgeben und fertig sein.

Wie sollen Sie solche Dinge in SQL tun? Verwenden Sie eine Art von CASE-Anweisung für die Pseudo-if? Eine Gewerkschaft oder eine andere schlaue Sache?

Edit: Ich benutze MS SQL.

Danke!

+3

Dies wird Ihnen helfen, testen http://stackoverflow.com/questions/5487892/sql-server-case-when-or-then-else-end-the-or-is-not- unterstützt – Meherzad

+0

Welche RDBMS verwenden Sie, MS SQL Server, MySQL, PostgreSQL ...? Für jeden von ihnen sind die Steuerflussanweisungen unterschiedlich gesetzt. – Yaroslav

+2

Sie haben Ihre Frage selbst beantwortet! Use-Case-Anweisungen! – Aditi

Antwort

91

Sie können die folgende SQL-Abfrage

IF ((SELECT COUNT(*) FROM table1 WHERE project = 1) > 0) 
    SELECT product, price FROM table1 WHERE project = 1 
ELSE IF ((SELECT COUNT(*) FROM table1 WHERE project = 2) > 0) 
    SELECT product, price FROM table1 WHERE project = 2 
ELSE IF ((SELECT COUNT(*) FROM table1 WHERE project = 3) > 0) 
    SELECT product, price FROM table1 WHERE project = 3 
+0

Wie funktioniert das in einem Codeigniter-Abfrage-Generator? –

+0

ORA-00900: sentencia SQL keine válida – delive

28

Die CASE-Anweisung ist in der Nähe von einer IF-Anweisung in SQL und wird auf allen Versionen von SQL Server unterstützt:

SELECT CASE <variable> 
      WHEN <value>  THEN <returnvalue> 
      WHEN <othervalue> THEN <returnthis> 
      ELSE <returndefaultcase> 
     END 
    FROM <table> 
+9

Dies beantwortet die Frage nicht. – Kaf

+0

Während CASE auf allen Versionen von MS SQL nützlich ist, haben neuere Versionen eine IF ELSE-Funktionalität. –

16

Stattdessen machen von mit EXISTS und COUNT verwenden nur @@ROWCOUNT:

select product, price from table1 where project = 1 

IF @@ROWCOUNT = 0 
BEGIN 
    select product, price from table1 where customer = 2 

    IF @@ROWCOUNT = 0 
    select product, price from table1 where company = 3 
END 
+2

+1 für eine gute Lösung –

+0

das ist keine gute Lösung ... verwendet keine inhärenten db Set-Funktionen. Ich denke nicht, dass es auch richtig ist, wenn es mehrere verschiedene Produkte gibt. eigentlich - ich denke, am besten kenntnisreich in dbs würde dies eine schlechte lösung. Das ist genau die Art von Dingen, die wir Leuten beibringen NICHT zu tun. – mson

+0

als Programmierer und nicht sehr in dbs, ich denke, diese Lösung sieht am einfachsten zu lesen und zu verstehen :) Allerdings bekomme ich mehrere Ergebnismengen, da es mehr als 1 Auswahl tut. Gibt es eine Möglichkeit, nur 1 Treffermenge zurückzugeben? Gibt es jemanden, der @smson darauf hinweist, dass das eine schlechte Idee ist? – Cotten

0

Es gibt eine Case-Anweisung, aber ich denke, die unten ist genauer/effizienter/einfacher zu lesen, was Sie wollen.

select 
    product 
    ,coalesce(t4.price,t2.price, t3.price) as price 
from table1 t1 
left join table1 t2 on t1.product = t2.product and t2.customer =2 
left join table1 t3 on t1.product = t3.product and t3.company =3 
left join table1 t4 on t1.product = t4.product and t4.project =1 
+0

Wenn Sie in 't1' keinen Treffer erhalten, werden keine Ergebnisse zurückgegeben. –

+0

lol - t1, t2, t3 zeigen auf die gleiche Tabelle (wie in Poster Anforderung) - aber ich sehe Ihren Punkt. gleiche Lösung obwohl – mson

+0

http://sqlfiddle.com/#!6/b847b/3, gut zum Testen. –

1

Bitte prüfen Sie, ob das hilft:

select TOP 1 
    product, 
    price 
from 
    table1 
where 
    (project=1 OR Customer=2 OR company=3) AND 
    price IS NOT NULL 
ORDER BY company 
+0

Dies wird ein Ergebnis zurückgeben, das zu _y_ der Bedingungen ohne Prioritätsreihenfolge passt. –

1

Mit SQL Server können Sie einfach einen CTE anstelle von IF/THEN-Logik verwenden, um es einfach aus Ihren bestehenden Anfragen zu kartieren und die Anzahl der ändern beteiligte Abfragen;

WITH cte AS (
    SELECT product,price,1 a FROM table1 WHERE project=1 UNION ALL 
    SELECT product,price,2 a FROM table1 WHERE customer=2 UNION ALL 
    SELECT product,price,3 a FROM table1 WHERE company=3 
) 
SELECT TOP 1 WITH TIES product,price FROM cte ORDER BY a; 

An SQLfiddle to test with.

Alternativ können Sie alle in einem SELECT kombinieren, um es für den Optimierer zu vereinfachen;

SELECT TOP 1 WITH TIES product,price FROM table1 
WHERE project=1 OR customer=2 OR company=3 
ORDER BY CASE WHEN project=1 THEN 1 
       WHEN customer=2 THEN 2 
       WHEN company=3 THEN 3 END; 

Another SQLfiddle.

0

--Ähnliche Antwort wie oben in den meisten Teilen. Code enthalten

DROP TABLE table1 
GO 
CREATE TABLE table1 (project int, customer int, company int, product int, price money) 
GO 
INSERT INTO table1 VALUES (1,0,50, 100, 40),(1,0,20, 200, 55),(1,10,30,300, 75),(2,10,30,300, 75) 
GO 
SELECT TOP 1 WITH TIES product 
     , price 
     , CASE WhereFound WHEN 1 THEN 'Project' 
       WHEN 2 THEN 'Customer' 
       WHEN 3 THEN 'Company' 
      ELSE 'No Match' 
      END AS Source 
FROM 
    (
    SELECT product, price, 1 as WhereFound FROM table1 where project = 11 
    UNION ALL 
    SELECT product, price, 2 FROM table1 where customer = 0 
    UNION ALL 
    SELECT product, price, 3 FROM table1 where company = 30 
    ) AS tbl 
ORDER BY WhereFound ASC 
Verwandte Themen