2013-02-26 10 views
81

ho bisogno di fare selezionare i dati da una tabella basata su un qualche tipo di priorità in questo modo:Puoi avere una logica if-then-else in SQL?

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 

Cioè, se ho trovato 3 prodotti con prezzi basati sul project = X, non voglio per selezionare il customer = Y . Voglio solo restituire le 3 righe risultanti e finire.

Come si dovrebbe fare cose come questa in SQL? Usa qualche tipo di dichiarazione CASE per la pseudo-if? Fai un sindacato o qualche altra cosa intelligente?

Modifica: sto usando MS SQL.

Grazie!

+3

Questo vi aiuterà a http://stackoverflow.com/questions/5487892/sql-server-case-when-or-then-else-end-the-or-is-not- supportato – Meherzad

+0

Quale tipo di RDBMS stai usando, MS SQL Server, MySQL, PostgreSQL ...? Per ognuno di essi il set di istruzioni del flusso di controllo è leggermente diverso. – Yaroslav

+2

Hai risposto alla tua domanda! Utilizzare le dichiarazioni del caso! – Aditi

risposta

91

È possibile effettuare la seguente query SQL

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

Come si fa in un costruttore di query code-code? –

+0

ORA-00900: Sentencia SQL no válida – delive

28

L'istruzione CASE è più vicino a un'istruzione IF in SQL, ed è supportato su tutte le versioni di SQL Server:

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

Questo non risponde alla domanda. – Kaf

+0

Mentre CASE è utile su tutte le versioni di MS SQL, le versioni più recenti hanno una funzionalità IF ELSE. –

16

Invece di utilizzando EXISTS e COUNT basta usare @@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 per una buona soluzione –

+0

questa non è una buona soluzione ... non utilizza le funzionalità intrinseche del db set. non penso sia corretto né dove ci sono più prodotti diversi. in realtà - penso che la maggior parte degli esperti in dbs considererebbe questa una soluzione scadente. questo è esattamente il tipo di cosa che cerchiamo di insegnare alle persone a NON fare. – mson

+0

essere un programmatore e non molto nel dbs, penso che questa soluzione sembri la più semplice da leggere e comprendere :) Tuttavia, ottengo più set di risultati poiché fa più di 1 selezione. C'è un modo per restituire solo 1 set di resout? Inoltre, qualcuno fa il backup di @mson perché è una cattiva idea? – Cotten

0

c'è una dichiarazione di caso, ma penso che il sotto sia più accurato/efficiente/più facile da leggere per quello che vuoi.

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

Se non si ottiene un hit in 't1', questo non restituirà alcun risultato. –

+0

lol - t1, t2, t3 puntano allo stesso tavolo (come nel requisito del poster) - ma vedo il tuo punto. stessa soluzione anche se – mson

+0

http://sqlfiddle.com/#!6/b847b/3, buona per i test. –

1

Si prega di verificare se questo aiuta:

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

Ciò restituirà un risultato che corrisponde a _query delle condizioni senza alcun ordine di priorità. –

1

Con SQL Server si può semplicemente utilizzare un CTE invece di IF/THEN logica per rendere più facile per mappare dalle query esistenti e modificare il numero di domande implicate;

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.

In alternativa, è possibile combinare tutto in uno SELECT per semplificarlo per l'ottimizzatore;

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

- Risposta simile come sopra per la maggior parte. Codice incluso per testare

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 
Problemi correlati