10

I am trying to label a single point with multiple labels, based on the attributes for that point. For example, if one of the attributes is equal to 1, I want to label it with a specific text string; and if another attribute is equal to 0, I want to label it with a different text string, etc. In addition, I want to use other attribute information to control the placement of the labels around the point, as well as their color.

Can multiple CASE WHEN/THEN expressions be stacked, to achieve the desired result? I have tried to include multiple WHEN/THEN statements inside my CASE expression, looking like this:

CASE
WHEN attribute1 = 1 THEN 'Apple'
WHEN attribute2 = 0 THEN 'Grape'
WHEN attribute3 >= 0 THEN 'Pear'
END

This returns the desired label for attribute1, but ignores the labels for the other two attributes. I believe this is because a CASE statement can only refer to a single variable/attribute at a time? If that is true, is there another conditional expression type I can use to achieve what I want? I'm trying to avoid having to add the point layer multiple times to my project, in order to label based on different attributes.

2
  • I am quite new of QGIS and so I'm sorry if I am asking a question already posted. Anyway, my question is: if I want to change just some values with a conditional statement while maintain the other ones as they are, what should I write? In Excel I would write: IF(cell1=x;"y";"") But in QGIS?: CASE WHEN "attribute 1"='x' THEN 'y'ELSE [????] Thank you so much Federica
    – FedericaZ
    Dec 1, 2016 at 16:59
  • You could use rule-based labelling with one rule for each of your case. It would then make it easy to display it how and where you want.
    – Victor
    Dec 2, 2016 at 11:42

2 Answers 2

11

The CASE statement can include multiple attributes in multiple conditions (or even in the same condition: WHEN attribute1 = 1 AND attribute2 = 0 THEN… is legal). But CASE evaluates the conditions in order and stops evaluating after it reaches the first condition that is satisfied. So, for your example, if attribute1 = 1 evaluates to TRUE, the rest of the conditions won't be evaluated.

You could do something like:

CASE WHEN attribute1 = 1 THEN 'Apple|' ELSE '' END
|| CASE WHEN attribute2 = 0 THEN 'Grape|' ELSE '' END
|| CASE WHEN attribute3 >= 0 THEN 'Pear|' ELSE '' END

and then use QGIS settings to introduce line breaks on the pipe ('|') character, which will at least get each word on its own line. (There is an extra pipe at the end which may have to be handled.) Note that the ELSE '' is necessary. Otherwise, if one of the conditions doesn't evaluate to TRUE, the CASE will return NULL, and NULL concatenated with any text will return NULL.

But to get to your larger question, I don't think you can have "Apple", "Grape", etc. appear in different positions around the feature, different colors, etc., even using data-defined properties. I think to achieve what you want you will have to create label-only duplicates of your layer, and have one layer print labels for attribute1 in the desired position and color, another layer print labels for attribute2 in the desired position and color, etc.

5
  • Not sure why your expression doesn't work for me, but I think this also works as an alternative: CASE WHEN "attribute1" = 1 THEN 'Apple|' ELSE '' END + CASE WHEN "attribute2 " = 0 THEN 'Grape|' ELSE '' END +...
    – Joseph
    Sep 9, 2015 at 15:13
  • @Joseph The information/ideas from both of you are certainly helpful. I was able to get the text of the different attributes to draw, using a '|' as a line break character, and stacking the CASE statements using a + symbol. However, as has been suggested, it looks like the best way for me to get the results I want (regarding color and placement) is to draw label-only duplicates of the layer.
    – Wes Kent
    Sep 9, 2015 at 17:38
  • Sorry, RTRIM() is a Postgres function not available in QGIS expression editor. QGIS does offer trim(), but this only removes whitespace, not specified characters like '|'. I've updated answer to remove this function. I was using it to strip the final pipe from the string. As pipe is replaced by newline, it may not make a difference, i.e. it won't be visible, but it might also cause label position to shift. Sep 9, 2015 at 17:54
  • Note that while + seems to work for string concatenation, || is standard SQL. In fact, if you check the buttons available in the expression editor, the tooltip for + is "Addition operator" while the tooltip for || is "String Concatenation". Sep 9, 2015 at 17:56
  • @LeeHachadoorian - Thank you for the info, that's good to know!
    – Joseph
    Sep 10, 2015 at 10:03
6

I think what you want to accomplish is rather a usecase for CASE WHEN... statements, but for 'rule based labels' (as suggested in one of the above comments):

enter image description here

For example, you may define a rule called 'Grape' and the expression for this rule would be "attribute1" = 0. For each rule you can set up each parameter (font color, size, placement, ...) separately. For the Grapes for example I've set this up as follows:

Filter expression, text color, label: enter image description here

Placement (here Bottom-left, or S-W): enter image description here

Additionally I've enabled Show all labels for this layer: enter image description here

The result looks like shown below (note the attribute Table): enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.