What is wrong is this mysql statement with case? - mysql

SELECT COUNT(*)
FROM PATIENTS A, RECALLS_AFTER_RESERV C
LEFT JOIN PATIENT_LAST_RESERV D
ON D.PATIENT_ID = C.PATIENT_ID
WHERE C.PATIENT_ID = A.ID
AND C.OFFICE_ID = A.OFFICE_ID
AND C.OFFICE_ID = ?
AND YEAR(CONVERT_TZ(C.RECALLS_AT, 'UTC', 'Asia/Tokyo')) = ?
AND (CASE
WHEN ISNULL(D.STARTS_AT) THEN
A.CHECKED_IN_AT
ELSE
D.STARTS_AT
END) >= CONVERT_TZ('2015-01-27 00:00:00', 'Asia/Tokyo', 'UTC')) AND (CASE
WHEN ISNULL(D.STARTS_AT) THEN
A.CHECKED_IN_AT
ELSE
D.STARTS_AT
END) <= CONVERT_TZ('2015-01-27 23:59:59', 'Asia/Tokyo', 'UTC') AND C.RECALLED_AT IS NULL AND C.STARTS_AT IS NULL
I want to use the case to determine whether the D.starts_at have value,if not, I use A.checked_in_at to replace the D.starts_at.but it gives an error

(case when isnull(D.starts_at) then A.checked_in_at else D.starts_at end) >= CONVERT_TZ('2015-01-27 00:00:00', 'Asia/Tokyo', 'UTC') )
I finally find the problem, the case statement is right. the problem is the redundant ) in the above.

Related

"IS NOT NULL" not producing the required results in mySQL

I am trying to build a report based of my table. Here is my table:
Following is the SQL query to get desired results.
SELECT
`user`,
SUM(
CASE
WHEN `event_time` >= '2021-04-01 00:00:00'
AND `event_time` <= '2021-04-16 23:59:59'
AND `sub_status` = 'TB'
THEN pause_sec
END
) AS 'Training Break',
SUM(
CASE
WHEN `event_time` >= '2021-04-01 00:00:00'
AND `event_time` <= '2021-04-16 23:59:59'
AND `sub_status` = 'SB1'
THEN pause_sec
END
) AS 'Short Break 1',
SUM(
CASE
WHEN `event_time` >= '2021-04-01 00:00:00'
AND `event_time` <= '2021-04-16 23:59:59'
AND `sub_status` = 'SB2'
THEN pause_sec
END
) AS 'Short Break 2',
SUM(
CASE
WHEN `event_time` >= '2021-04-01 00:00:00'
AND `event_time` <= '2021-04-16 23:59:59'
AND `sub_status` = 'LB'
THEN pause_sec
END
) AS 'Long Break'
FROM
`vicidial_agent_log`
GROUP BY `user`
I am looking to exclude entries which have all null values and following is my syntax but it is not working and produces the same results.
FROM
`vicidial_agent_log`
WHERE 'Training Break' IS NOT NULL
AND 'Short Break 1' IS NOT NULL
AND 'Short Break 2' IS NOT NULL
AND 'Long Break' IS NOT NULL
GROUP BY `user`
Kindly help here or share a post that can help. I have been trying to find but
Don't use single quotes for column names/aliases, because for example 'Training Break' in an expression like 'Training Break' IS NOT NULL is interpreted as a string literal which of course is not null.
In MySql you can use backticks to surround column names.
Also, the columns Training Break, Short Break 1, Short Break 2 and Long Break are the result of aggregate functions so they can't be used in a WHERE clause. Instead use a HAVING clause.
Finally, since you want the rows where at least 1 of these columns is not null you should use the operator OR instead of AND:
FROM
`vicidial_agent_log`
GROUP BY `user`
HAVING `Training Break` IS NOT NULL
OR `Short Break 1` IS NOT NULL
OR `Short Break 2` IS NOT NULL
OR `Long Break` IS NOT NULL
Or:
FROM
`vicidial_agent_log`
GROUP BY `user`
HAVING COALESCE(`Training Break`, `Short Break 1`, `Short Break 2`, `Long Break`) IS NOT NULL
First, move the common part of the SUM() expressions to the WHERE clause.
Second, fix the date logic so you are not missing a second.
I also strongly, strongly recommend using column names that do not need to be escaped. So:
SELECT user,
SUM(CASE WHEN sub_status` = 'TB' THEN pause_sec END) AS Training_Break,
SUM(CASE WHEN sub_status = 'SB1' THEN pause_sec END) AS Short_Break_1,
SUM(CASE WHEN sub_status = 'SB2' THEN pause_sec END) AS Short_Break_2,
SUM(CASE WHEN sub_status = 'LB' THEN pause_sec END) AS Long_Break
FROM vicidial_agent_log
WHERE event_time >= '2021-04-01' AND
event_time < '2021-04-17'
GROUP BY user;
This will probably eliminate the NULL values and speed up the query. However, if there are still NULL values in an entire row, it is because there are rows that don't have one of these statuses. So, just check for them:
SELECT user,
SUM(CASE WHEN sub_status` = 'TB' THEN pause_sec END) AS Training_Break,
SUM(CASE WHEN sub_status = 'SB1' THEN pause_sec END) AS Short_Break_1,
SUM(CASE WHEN sub_status = 'SB2' THEN pause_sec END) AS Short_Break_2,
SUM(CASE WHEN sub_status = 'LB' THEN pause_sec END) AS Long_Break
FROM vicidial_agent_log
WHERE event_time >= '2021-04-01' AND
event_time < '2021-04-17' AND
sub_status IN ('TB', 'SB1', 'SB2', 'LB')
GROUP BY user;
SQL is very powerful in letting you filter before or after aggregation. However, it is usually much better (from a performance perspective) to filter before aggregating.
I also advise you to use identifiers that do not need to be escaped. And, never use single quotes for anything other than string and date literals.

Grouping different column into one row

How to make one row in different rows and column
SELECT
internal_id, store_id, user_id, shift_info,
DATE(log_datetime) dates,
(case when log_action = '0' then TIME(log_datetime) end) as time_in,
(case when log_action = '0' then CONCAT(log_lat, ",", log_lng) end) as loc_in,
(case when log_action = '1' then TIME(log_datetime) end) as time_out,
(case when log_action = '1' then CONCAT(log_lat, ",", log_lng) end) as loc_out
FROM
attendance_store_user
WHERE
user_id = "A4CBD64F-D21C-5612-CCF5-497892B62E76"
i want result like this :
You could try using a join of the same table filter for null time_out and time_in
select a.dates, a.store_id, a,time_in, b.time_out
FROM attendance_store_user a
INNER JOIN attendance_store_user b on a.dates = b.dates
and a.user_id = b.user_id
and a.time_out is null
and b.time_in is null
WHERE a.user_id = "A4CBD64F-D21C-5612-CCF5-497892B62E76"

MySQL CASE , SUM, GROUP BY

I want sum of payment status from two differnt columns based on paymentstatus value - but this query returns null for sum. Why is it not working?
select payment_status,
CASE
WHEN 'PAID' THEN sum(paid_amount)
when 'Not Paid' then sum(total_amount_due )
END
from monthly_fee
group by payment_status;
select sum(CASE WHEN payment_status = 'PAID' THEN paid_amount else 0 end) as paid,
sum(CASE WHEN payment_status = 'Not Paid' THEN total_amount_due else 0 end) as due
from monthly_fee
If you want this conditionally, you need to include the column in the case:
select payment_status,
(case payment_status
when 'Paid' then sum(paid_amount)
when 'Not Paid' then sum(total_amount_due )
end)
from monthly_fee
group by payment_status;
This seems like a strange way to write the query, unless you really want two rows.
Your WHEN clauses aren't a condition.
I'd expect to see something like
select payment_status,
CASE
WHEN payment_status = 'PAID' THEN sum(paid_amount)
when payment_status = 'Not Paid' then sum(total_amount_due )
END
from monthly_fee
group by payment_status;
You can try the following query:
select sum(if(payment_status = 'PAID', paid_amount, 0)
+ if(payment_status = 'Not Paid', total_amount_due, 0))
from monthly_fee
group by payment_status;

How to get separate fields data with IF() statement in single query

I am trying to get the unpaid and partial amount separately in single query
select
if(i.status = 'unpaid', sum(i.total_amount), '') unpaid,
if(i.status = 'partial', sum(i.paid_amount), '') partial
from {CI}invoices i
where
i.customer_id = ? and
date(i.invoice_date) < '2014-01-01' and
i.status not like 'paid%'
But i am getting blank i think that is because i used '' in if statement, i also tried with
if(i.status = 'unpaid', sum(i.total_amount) as unpaid, sum(i.paid_amount) as paid)
which is wrong because i can't use as in IF() condition. Can anyone please help me to resolve this query or suggest any alternative way??
Try the following:
SELECT
SUM( IF(i.status = 'unpaid', i.total_amount, 0) ) unpaid,
SUM( IF(i.status = 'partial', i.paid_amount, 0) ) partial
FROM {CI}invoices i
WHERE
i.customer_id = ? AND
date(i.invoice_date) < '2014-01-01' AND
i.status IN ('unpaid', 'partial')
Give this a go:
select
sum(case when i.status = 'unpaid' then i.total_amount else 0 end) as unpaid,
sum(case when i.status = 'partial' then i.paid_amount else 0 end) as partial
from {CI}invoices i
where
i.customer_id = ? and
date(i.invoice_date) < '2014-01-01' and
i.status not like 'paid%'
You have to cross join table to itself to get paid and unpaid in the same row:
SELECT
sum(iu.total_amount) unpaid,
sum(ip.paid_amount) partial
FROM {CI}invoices iu
CROSS JOIN {CI}invoices ip
where
ip.customer_id = ? AND iu.customer_id = ? AND
date(ip.invoice_date) < '2014-01-01' AND date(iu.invoice_date) < '2014-01-01' AND
iu.status = 'unpaid' AND ip.status = 'partial'

Something wrong with my mySQL query

SELECT t.id, t.active, t.off, t.duration, t.user
FROM table t
WHERE t.active = '0000-00-00 00:00:00'
OR t.duration != '0'
AND t.user = '1'
AND t.off = '0000-00-00 00:00:00'
LIMIT 0 , 30
Basically it's ignoring the t.off part, whats wrong?
Thank you =)
(the query was edited for an example purpose, the real query is similar to this but with other table names, etc)
== [ Update ] ==
SELECT t.active, t.off, t.duration, t.user
FROM table t
WHERE (
t.active = '0000-00-00 00:00:00'
OR t.duration != '0'
)
AND t.user = '1'
AND t.off = '0000-00-00 00:00:00'
LIMIT 0 , 30
UNION ALL
SELECT c.active, c.off, c.duration, c.user
FROM chair c
WHERE (
c.active = '0000-00-00 00:00:00'
OR c.duration != '0'
)
AND c.user = '1'
AND c.off = '0000-00-00 00:00:00'
You should use parenthesis, to group conditions (and / or), to make sure they are evaluated in the order you want.
For example, do you want to following :
SELECT t.id, t.active, t.off, t.duration, t.user
FROM table t
WHERE t.active = '0000-00-00 00:00:00'
OR (
t.duration != '0'
AND t.user = '1'
AND t.off = '0000-00-00 00:00:00'
)
LIMIT 0 , 30
Or the following :
SELECT t.id, t.active, t.off, t.duration, t.user
FROM table t
WHERE (
t.active = '0000-00-00 00:00:00'
OR t.duration != '0'
)
AND t.user = '1'
AND t.off = '0000-00-00 00:00:00'
LIMIT 0 , 30
Or maybe something else ?
Using parenthesis will make your query easier to read -- and will help making sure the conditions are evaluated properly.