CASE Statement in SQL WHERE clause - mysql

I'm trying to fetch data from table where I'm using a CASE condition in the WHERE clause and currently I'm using following query:-
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND (
STATUS = 'Sold'
OR STATUS = 'In Stock'
OR STATUS = 'Ref'
)
AND CASE WHEN (
STATUS = 'Sold'
)
THEN delivery_date >= '2012-08-01'
END
But it returns 0 for total and NULL for purchase.

From your comment.
I want to use Case Statement, could u pls clarify me about case statament in where clause
You can use CASE statement in WHERE like this:
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND ( STATUS = 'Sold'
OR STATUS = 'In Stock'
OR STATUS = 'Ref')
AND CASE STATUS
WHEN 'Sold'
THEN delivery_date >= '2012-08-01'
ELSE 1=1
END
Here you need to use ELSE 1=1. otherwise you will not get desired result. For more explanation see this SQLFiddle

I don't think that CASE can work that way. What you want is a slightly more complex expression as your WHERE clause. Probably something like this:
SELECT count(enq_id) AS total, sum(purchase_amount) AS purchase
FROM temp_stock
WHERE purchase_date <> '0000-00-00'
AND purchase_date < '2012-08-01'
AND (
(STATUS = 'Sold' AND delivery_date >= '2012-08-01')
OR STATUS = 'In Stock'
OR STATUS = 'Ref'
)

Related

Mysql if Null or Empty String then Show N/A

Hello I'm new to mysqsl and I'm trying to display N/A if the return data is empty or NULL but my query is unrecognized statement type. What do you think is wrong with my query? wrong placement of code?
CASE when 'Earliest Time Opened' = '' or 'Earliest Time Opened' is 'Null'
then 'N/A'
ELSE
SELECT (date_format(d.date_opened, '%r') as 'Earliest Time Opened'
FROM daily_report d JOIN userinfo ui
ON d.userid= ui.id
WHERE d.date_opened >= date_sub(curdate(), interval 0 day)
AND d.survey_at_what_blh = 'Bagong Silang' AND ui.status='Employee'
ORDER BY d.date_opened DESC
limit 1
END
Use IF with ISNULL here:
SELECT IF(ISNULL(d.date_opened), 'N/A', DATE_FORMAT(d.date_opened, '%r')) AS `Earliest Time Opened`
FROM daily_report d
INNER JOIN userinfo ui ON d.userid = ui.id
WHERE
d.date_opened >= CURDATE() AND
d.survey_at_what_blh = 'Bagong Silang' AND
ui.status = 'Employee'
ORDER BY
d.date_opened DESC
LIMIT 1;
If you really wanted to use a CASE expression, then it would need to appear inside the select clause, something like this:
SELECT CASE WHEN DATE_FORMAT(d.date_opened, '%r') IS NOT NULL
THEN DATE_FORMAT(d.date_opened, '%r')
ELSE 'N/A' END AS `Earliest Time Opened`
But COALESCE is much more terse and appropriate here.

selecting multiple fields using in where clause

I have a MySQL query and this is used to bring up certain events. The event_type and etype will change depending on what someone chooses in the form.
Below is what is added to the query based on a form on the webpage.
and event_type = '54' and etype = 'SP'
the full query is
select tevent.event_name, tevent.event_type, min(e_dates.event_date) as eventdate,
tevent.status, tevent.etype
from (tevent LEFT JOIN event_dates on tevent.eventid=event_dates.eventid)
Where status <> 'delete'
AND YEAR(e_dates.event_date) >= YEAR( CURDATE( ) ) and event_type = '54' and etype = 'SP')
group by tevent.eventid
order by (case when tevent.status = 'closed' and e_dates.event_date >= curdate() then 0 else 1 end),
(case when find_in_set(`status`, 'open,pending,approved') then 0 else 1 end),
e_dates.event_date asc, tevent.eventid ASC
This works perfectly for what I need. I shows all the events that are a certain event types and event category.
However, I want ALL queries to include the following statement
((event_type = '54' and etype = 'SM') or (event_type = '50' and
event_prelim = '2'))
the above statement will add the seminars to all event calendars, but will also show each particular event type based on what the person chooses.
I suppose your WHERE clause could look like this
WHERE status <> 'delete'
AND YEAR(e_dates.event_date) >= YEAR(CURDATE())
AND (
event_type NOT IN ('50','54')
OR event_type IS NULL
OR (event_type = '54' AND etype IN ('SP','SM'))
OR (event_type = '50' AND event_prelim = '2')
)
AND's are evaluated before the OR's.
So when using both AND's and OR's in the criteria, putting the parentheses does matter.

mysql SUM column on WHERE condition

Im trying to get a total sum of all the columns that meet a condition. Here is my current setup
SELECT
COUNT(order_type = 'BUY') AS buy_fill,
COUNT(order_type = 'SELL') AS sell_fill,
SUM(btc_total) AS fill_sum
FROM fill_orders
WHERE coin_id = '$coin'
AND time_stamp >= DATE_SUB(NOW(), INTERVAL 55 SECOND)
This is what I have now and its counting how many types of buy and sell orders I have and is also giving me sum of all orders but I need to the break the sum of the orders into BUY orders and SELL orders.
Heres the code that I'm trying trying to make work. I've added (btc_total WHERE order_type = 'BUY') and SUM(btc_total WHERE order_type = 'SELL')
SELECT
COUNT(order_type = 'BUY') AS buy_fill,
COUNT(order_type = 'SELL') AS sell_fill,
SUM(btc_total) AS fill_sum,
SUM(btc_total WHERE order_type = 'BUY') AS buy_total
SUM(btc_total WHERE order_type = 'SELL') AS sell_total
FROM fill_orders
WHERE coin_id = '$coin'
AND time_stamp >= DATE_SUB(NOW(), INTERVAL 55 SECOND)
Change this:
SUM(btc_total WHERE order_type = 'BUY') AS buy_total
to this:
SUM(IF(order_type='BUY',btc_total,NULL)) AS buy_total
The MySQL IF() function evaluates the first argument as a boolean, if that's TRUE, it returns the second argument, else it returns the third argument.
The IF() will be evaluated for each row, and the return from that expression will get totaled up by the SUM() aggregate.
or, use the more ANSI-standard equivalent to achieve the same result:
SUM(CASE WHEN order_type = 'BUY' THEN btc_total END) AS buy_total
This pattern is commonly referred to as "conditional aggregation".
For the "counts" we can replace COUNT with SUM, like this:
SUM(order_type = 'BUY') AS buy_fill
MySQL evaluates the equality comparison as a boolean, which returns 1, 0 or NULL, which are then totaled up by the SUM aggregate. (A COUNT of that would include zeros and ones, not just the ones.)
The above is equivalent to
SUM( CASE
WHEN order_type = 'BUY' THEN 1
WHEN order_type <> 'BUY' THEN 0
ELSE NULL
END
) AS buy_fill
If we want to use a COUNT aggregate, we could do it like this:
COUNT(IF(order_type = 'Buy',1,NULL)) AS buy_fill
(We could use any non-null value in place of 1, and get an equivalent result.)
"conditional aggregates" conventionally contain a case expression
SELECT
COUNT(CASE WHEN order_type = 'BUY' THEN order_type END) AS buy_fill
, COUNT(CASE WHEN order_type = 'SELL' THEN order_type END) AS sell_fill
, SUM(btc_total) AS fill_sum
, SUM(CASE WHEN order_type = 'BUY' THEN btc_total ELSE 0 END) AS buy_total
, SUM(CASE WHEN order_type = 'SELL' THEN btc_total ELSE 0 END) AS sell_total
FROM fill_orders
WHERE coin_id = '$coin'
AND time_stamp >= DATE_SUB(NOW(), INTERVAL 55 SECOND)

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 do a SELECT for total from beginning until the specified date in MySQL?

I have entry table:
I need to do a SELECT to receive 'Date', 'Number of entries' (in that date), 'Total number of entries until that date'.
When I do the SELECT:
SELECT e1.*,
(select count(*) from entry where date(dateCreated) <= e1.date) as Total
from (
SELECT
DATE(e.dateCreated) as "Date",
count(e.dateCreated) as "No of Entries",
sum( case when e.premium='Y' then 1 else 0 end ) as Premium,
sum( case when e.free='Y' then 1 else 0 end ) as Free,
sum( case when e.affiliateID IS NOT NULL then 1 else 0 end) as Affiliate
FROM entry e
WHERE e.competitionID=166
GROUP BY DATE(e.dateCreated)
) as e1
ORDER BY Date DESC
I've got a result table
but the column 'Total' has a wrong data.
How the correct select should be? Is this logic of select is the best and more efficient one?
Here is a demo
If it is just the 5 vs 7 that is off I think it is because that subquery in your select list, which accesses the inline view e1 (which is filtered to competitionID = 166), is not itself filtered when also utilizing the original entry table (unfiltered). You have to filter the original table to that competitionID as well.
Notice line 3 in sql below (only change)
SELECT e1.*,
(select count(*) from entry where date(dateCreated) <= e1.date
and competitionID=166) as Total
from (
SELECT
DATE(e.dateCreated) as "Date",
count(e.dateCreated) as "No of Entries",
sum( case when e.premium='Y' then 1 else 0 end ) as Premium,
sum( case when e.free='Y' then 1 else 0 end ) as Free,
sum( case when e.affiliateID IS NOT NULL then 1 else 0 end) as Affiliate
FROM entry e
WHERE e.competitionID=166
GROUP BY DATE(e.dateCreated)
) as e1
ORDER BY Date DESC
Fiddle - http://sqlfiddle.com/#!9/e5e88/22/0