I have a "user_activity_log" table that contains the fields "id", "client_id", "hitdatetime", and "action".
id
client_id
hitdatetime
action
2661715
17
2020-09-18 11:30:43
visit
2661716
17
2020-09-18 11:30:54
registration
2661717
17
2020-09-18 11:31:16
visit
It is necessary to output:
"client_id", from the input table
"visit_dt", that is associated to the "hitdatetime" field when the "action" equals to 'visit', otherwise it is null
"is_registration", that is associated to 1 if "action" equals to 'registration', otherwise it is 0
The CASE statement is mandatory for this query.
I've started writing the query, but I don't know what to put in place of the signs ???.
SELECT client_id,
CASE WHEN action = 'visit' THEN ??? ELSE 'NULL' END as visit_dt,
CASE WHEN action = 'registration' THEN '1' ELSE '0' END as is_registration
FROM user_activity_log;
Can you provide help?
Try with the following one:
SELECT client_id,
CASE WHEN action = 'visit'
THEN hitdatetime END AS visit_dt,
CASE WHEN action = 'registration'
THEN 1
ELSE 0 END AS is_registration
FROM user_activity_log;
Side notes:
if the ELSE clause of the CASE statement should evaluate to NULL, you are not required to specify it as it is default value
use numeric values in place of strings if the nature of your input should be numeric
always prefer using NULL instead of the corresponding "NULL" string, as sql provides a whole set of functions that can handle NULL values in a better way
is_registration should really be boolean. Also makes the query simpler:
SELECT client_id
, CASE WHEN action = 'visit' THEN hitdatetime END AS visit_dt
, action = 'registration' AS is_registration -- !
FROM user_activity_log;
If action can be NULL, so can be is_registration. If you want false instead of null, use one of these:
action IS NOT DISTINCT FROM 'registration' AS is_registration
Or:
COALESCE(action = 'registration', false) AS is_registration
Related:
Change varchar to boolean in PostgreSQL
Why does PostgreSQL not return null values when the condition is <> true
Best way to check for "empty or null value"
I need to make a query that verify:
if type_answer is equal to Multipla Escolha so i only have to return the records that are not null in correct_answer_description_id
If the type_answer is not equal to Multipla Escolha, don’t make this rule.
So, i try this way:
SELECT * FROM book_unit_question
WHERE book_unit_id = 2
AND status = false
CASE WHEN type_answer = 'Multipla Escolha' THEN
correct_answer_description IS NOT NULL
but i'm getting:
ERROR: syntax error at or near "CASE"
I don't think CASE is the easiest approach here. Can you try the re-written query below?
SELECT * FROM book_unit_question
WHERE book_unit_id = 2
AND status = false
AND (type_answer is null or type_answer != 'Multipla Escolha' or
correct_answer_description IS NOT NULL)
Getting rid of the negative yields negative construct "type_answer is not equal to Multipla Escolha, don’t make this rule" by rephrasing "type answer equal Multipla Escolha then apply this rule. Also applying "only return the records that are not null in correct_answer_description_id". We arrieve at:
select *
from book_unit_question
where book_unit_id = 2
and status = false
and type_answer = 'Multipla Escolha'
and correct_answer_description is not null;
In my Ruby on Rails app I'm using blazer(https://github.com/ankane/blazer) and I have the following sql query:
SELECT *
FROM survey_results sr
LEFT JOIN clients c ON c.id = sr.client_id
WHERE sr.client_id = {client_id}
This query works really well. But I need to add conditional logic to check if client_id variable is present. If yes then I filter by this variable, if not then I not launching this where clause. How can I do it in PostgreSQL?
Check if its null OR your condition like this:
WHERE {client_id} IS NULL OR sr.client_id = {client_id}
The WHERE clause evaluate as follow: If the variable is empty, then the WHERE clause evaluate to true, and therefore - no filter. If not, it continue to the next condition of the OR
If anyone faced with the psql operator does not exist: bigint = bytea issue, here is my workaround:
WHERE ({client_id} < 0 AND sr.client_id > {client_id}) OR sr.client_id = {client_id}
Please consider that, client_id generally cannot be negative so you can use that information for eleminating the operation cast issue.
My solution:
I use spring data jpa, native query.
Here is my repository interface signature.
#Query(... where (case when 0 in :itemIds then true else i.id in :itemIds end) ...)
List<Item> getItems(#Param("itemIds) List<Long> itemIds)
Prior calling this method, I check if itemIds is null. If yes, I set value to 0L:
if(itemIds == null) {
itemIds = new ArrayList<Long>();
itemIds.add(0L);
}
itemRepo.getItems(itemIds);
My IDs starts from 1 so there is no case when ID = 0.
I'm running this code:
SELECT hID
FROM logonsHistory
WHERE aIDs NOT LIKE '%''101''%' AND
CASE src
WHEN 0 THEN
uID IN(29,41,42,45,49,50,57,73,83,107,166,349,356,367,375,376,416,471,472,473,474,481)
END
I get this error:
Incorrect syntax near the keyword 'IN'
I have no idea what's wrong.
A CASE statement is not appropriate in this case. Just use a simple OR condition:
SELECT hID
FROM logonsHistory
WHERE aIDs NOT LIKE '%''101''%'
AND (
src <> 0 -- add a COALESCE here if src can be NULL
OR uID IN(29,41,42,45,49,50,57,73,83,107,166,349,356,367,375,376,416,471,472,473,474,481)
)
... which basically is the equivalent of only applying the uID filtering if src = 0, which is what you appeared to be trying to accomplish with your query.
It sounds like you don't have to use CASE please test this
SELECT hID
FROM logonsHistory
WHERE aIDs NOT LIKE '%''101''%'
AND ( (src = 0 --scr is 0 => must have uid in the list
AND UID IN (29,41,42,45,49,50,57,73,83,107,166,349,356,367,375,376,416,471,472,473,474,481))
OR src <> 0) --else src is not 0 and there is no additional condition
i have a doubt on your not like condition have you tested it alone?
Guess this is what you are looking for
WHERE aIDs NOT LIKE '%''101''%' or
(
src = 0
AND
uID IN(29,41,42,45,49,50,57,73,83,107,166,349,356,367,375,376,416,471,472,473,474,481
)
It looks like your statement is not formatted properly. you placed a condition rather than a value to set within "When 0 then ...... END
the uID IN(29,41,42,45,49,50,57,73,83,107,166,349,356,367,375,376,416,471,472,473,474,481) you have there is a condition and shouldn't have been there
The when part of a case statement should select a single value. what you are trying to do is to check for a condition.
Or if you are checking for uid in those values, you should do
case when src = 0 then
case when uID IN (29,41,42,45,49,50,57,73,83,107,166,349,356,367,375,376,416,471,472,473,474,481)
then 'It is a Client ID'
-- add another when or else part here if required
end
else 'Not a UID and not a Client ID'
end
In languages such as JavaScript you can have 2 conditional statements and "protect" the second one with the first one. For instance:
if( scarryObject != null && scarryObject.scarryMethod() ) { ... }
// if scarryObject is null scarryMethod will not be called
I thought I would achieve the same in SQL like so:
where int_date > 19500101
and month(CONVERT(smalldatetime, ... int_date))
The problem here is that if int_date is some "bad" value like -1, 0, 1 the conversion will fail and the sp will stop with an error. I thought the first check int_date > 19500101 would get evaluated first and if false the second condition would be skipped.
It seems like it does not work like this... or? Is there any other way of doing this?
Thanks!
Your query is syntactically not correct, as the clausemonth(CONVERT.... is not a condition.
Let's assume you want to compare with a certain number, a possible way of expressing what you want would be
SELECT *
FROM myTable
WHERE case
when int_date > 19500101
then -1
else month(CONVERT(smalldatetime, ... int_date))
end = #YourMonth
You would 'protect' the evaluation of the 'month' and not the condition.
You could try splitting the query into two. Here is the concept:
SELECT *
FROM (
SELECT *
FROM myTable
WHERE int_date > 19500101
) t
WHERE month(CONVERT(smalldatetime, ... t.int_date))