'IF' dans l'instruction 'SELECT' - choisissez la valeur de sortie en fonction des valeurs de colonne

685
SELECT id, amount FROM report

Je dois amountêtre amountsi report.type='P'et -amountsi report.type='N'. Comment ajouter ceci à la requête ci-dessus?

Michael
la source

Réponses:

1025
SELECT id, 
       IF(type = 'P', amount, amount * -1) as amount
FROM report

Voir http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html .

En outre, vous pouvez gérer lorsque la condition est nulle. Dans le cas d'un montant nul:

SELECT id, 
       IF(type = 'P', IFNULL(amount,0), IFNULL(amount,0) * -1) as amount
FROM report

La partie IFNULL(amount,0)signifie que lorsque le montant n'est pas nul, le montant du retour renvoie 0 .

Felipe Buccioni
la source
5
Je me demande s'il y a un avantage à utiliser cet IFNULL au lieu de COALESCE ici?
Chris
4
De la source mysql, je remarque 2 définitions de coalesce, une avec 2 arguments et l'autre avec une liste d'arguments, mais ifnull invoque la coalesce avec 2 paramètressql/item_cmpfunc.h 722: Item_func_ifnull(Item *a, Item *b) :Item_func_coalesce(a,b) {}
Felipe Buccioni
2
La réponse n'est pas correcte s'il existe des types de rapports différents de «N» et «P», voir le commentaire de BadHorsie dans la meilleure solution «déclaration de cas».
Trygve
3
@Trygve La question est pour 2 conditions, et à la recherche d'une IFdéclaration, qu'est-ce qui ne va pas?
Felipe Buccioni
2
@Felipe, la réponse n'est pas nécessairement correcte à 100%, il pourrait y avoir d'autres types de rapports que N et P. Dans votre cas, cela pourrait conduire à une erreur, en sélectionnant -montant si le type de rapport (par exemple) est 'E'. Cependant, la question ne mentionne pas s'il existe d'autres types de rapports, donc je supprime mon downvote. J'aime simplement programmer de manière défensive dans ces cas, donc je me dirige vers d'autres lecteurs.
Trygve
255

Utilisez une casedéclaration:

select id,
    case report.type
        when 'P' then amount
        when 'N' then -amount
    end as amount
from
    `report`
mellamokb
la source
5
@Evan: Vrai. Je les utilise pour plus de clarté. Non pas que cela affecte quoi que ce soit de toute façon.
mellamokb
3
Je préfère la syntaxe standard ANSI à la syntaxe personnalisée pour une base de données particulière.
Gordon Linoff
2
Il s'agit de la meilleure solution, car la solution de réponse acceptée n'est pas nécessairement appropriée s'il existe d'autres valeurs pour report.type ou si un nouveau report.type est introduit à une date ultérieure. Ça dit if report.type = 'P' use amount, otherwise use -amount for anything else. il ne considérera pas le type s'il n'est pas «P».
BadHorsie
97
SELECT CompanyName, 
    CASE WHEN Country IN ('USA', 'Canada') THEN 'North America'
         WHEN Country = 'Brazil' THEN 'South America'
         ELSE 'Europe' END AS Continent
FROM Suppliers
ORDER BY CompanyName;
user1210826
la source
43
select 
  id,
  case 
    when report_type = 'P' 
    then amount 
    when report_type = 'N' 
    then -amount 
    else null 
  end
from table
a chanté kaul
la source
15

Le moyen le plus simple consiste à utiliser un IF () . Oui, Mysql vous permet de faire de la logique conditionnelle. SI la fonction prend 3 paramètres CONDITION, TRUE OUTCOME, FALSE OUTCOME.

La logique est donc

if report.type = 'p' 
    amount = amount 
else 
    amount = -1*amount 

SQL

SELECT 
    id, IF(report.type = 'P', abs(amount), -1*abs(amount)) as amount
FROM  report

Vous pouvez ignorer abs () si tous les non sont uniquement positifs

aWebDeveloper
la source
12
SELECT id, amount
FROM report
WHERE type='P'

UNION

SELECT id, (amount * -1) AS amount
FROM report
WHERE type = 'N'

ORDER BY id;
linitux
la source
Comme les ensembles de résultats s'excluent mutuellement, je préfère UNION ALL ici.
Arth
4

Vous pouvez également essayer ceci

 SELECT id , IF(type='p', IFNULL(amount,0), IFNULL(amount,0) * -1) as amount FROM table
Règles de base
la source