i m want to replace CASE WHEN in this query
SELECT label ,date,count(id) AS nb, count(CASE WHEN label='test' THEN 1 END) AS nb_test
FROM
sil_test,sil_data
WHERE
sil_test.id_t=sil_data.id_t
GROUP BY
label, date
any idea??
Here is another version of this query that works with MySQL:
SELECT label ,date,count(id) AS nb, sum(label = 'test') AS nb_test
FROM sil_test join
sil_data
on sil_test.id_t = sil_data.id_t
GROUP BY label, date;
I'm not sure what problem this solves, except for replacing ANSI standard syntax with MySQL-specific functionality. And, of course, fixing the joins so they are explicit (much, much, much recommended).
Related
I want to write a query to determine the success rate for every day for each different mode. I did write a query that'll just group by date and mode which serves my purpose but one of my seniors wrote this following query which also works but I am just unable to understand how the if clause is working. I'll add a bit of the query here -
SELECT
dt,
sum(if(mode='A',success,0))AS a_s,
sum(if(mode='A',total,0))AS a_t,
sum(if(mode='B',success,0))AS b_s,
sum(if(mode='B',total,0))AS b_t,
sum(if(mode='C',success,0))AS c_s,
sum(if(mode='C',total,0))AS c_t,
sum(if(mode='D',success,0))AS d_s,
sum(if(mode='D',total,0))AS d_t,
sum(if(mode NOT in('A','B','C','D'),success,0))AS other_s,
sum(if(mode NOT in('A','B','C','D'),total,0))AS other_t
FROM
(SELECT
mode,
date(addedon)AS dt,
sum(if(status in('success','partial'),1,0))AS success,
count(*)AS total
FROM `a_huge_ass_table`
WHERE `studentid`=159633 AND addedon>'2021-01-15'
GROUP BY mode,date(addedon)
)AS t
Here I am unable to understand how sum(if(mode='A',success,0))AS a_s, - this if clause is working. If the condition is true then the clause is returning success? how does that work does adding success also somehow verify that its status is a success case? I cant find this on google.
First, if() is not standard SQL. I recommend rewrite this using case:
sum(case when mode = 'A' then success else 0 end) as a_s,
sum(case when mode = 'A' then total else 0 end) as a_t,
and so on.
Second, this query is missing the final group by dt. Otherwise it produces one row, rather than a separate row for each dt value.
This is called conditional aggregation. Every row in the final result set represents a group of rows from the subquery. Within this group, some have mode = 'A' and some do not. For the ones with mode = 'A' the above sums the value of success and total.
There is no need for a subquery by the way. That just slows down the query. I would recommend writing the query as:
SELECT date(addedon) as dt
SUM( mode = 'A' AND status IN ('success', 'partial') ) as a_success,
SUM( mode = 'A' ) as a_total,
. . .
FROM `a_huge_ass_table`
WHERE studentid = 159633 AND addedon >= '2021-01-15'
GROUP BY date(addedon);
Note that this uses a MySQL extension where boolean expressions are treated as integers, with "1" for true and "0" for false.
I'm trying to get the count of items in my table where it should satisfy these conditions
status = active
type = Pre-order
date = $date_input
OR
status = active
type = Both
date = $date_input
I'm trying to use this statement but I'm pretty sure it's messed up.
SELECT COUNT(id) as count_date from date_restriction
where (date='$date_input' AND status='active' AND type='Pre-order')
OR (date='$date_input' AND status='active' AND type='Both')
I also tried this to no avail
SELECT COUNT(id) as count_date from date_restriction
where date='$date_input' AND status='active' AND type='Pre-order' OR type='Both'
Whe you have mixed AND and OR condition you need () for the or clause
SELECT COUNT(id) as count_date
from date_restriction
where date='$date_input'
AND status='active'
AND ( type='Pre-order' OR type='Both')
or instear of several or condition you could use a IN clause
AND type IN ('Pre-order', 'Both')
anyway you should avoid the use of php var in SQL you are at risk for sqlinjection .. for avoid this you should take a look at prepared statement and binding param for your db driver
Your code should work. I would write this as:
select count(*) as count_date
from date_restriction
where date = ? AND status = 'active' AND
type in ('Pre-order', 'Both');
Note: The ? is for a parameter so you are not munging the query string with input values.
If I had to guess why this isn't working, I would speculate that one or both of the dates have a time component. You might try:
where date(date) = date(?) . . .
to be sure you are matching on the date, regardless of time.
SELECT count(id) as count_date
FROM date_restriction
WHERE date='$date_input' AND status='active' AND (type='Pre-order' OR type='Both');
Here, date and status both fields are common in your case; hence, don't wrap it in parenthesis whereas, add OR condition for type field only and con-cat it with AND in WHERE clause.
I'm trying to inherit value from previous row (based on correct subscription_id + checking for IS NULL subscription_status), but something goes wrong and I get incorrect value.
Take a look at screenshot.
If I'm not mistaken it also called last non-null puzzle, but examples of possible solution for other DB provide window function with IGNORE NULLS.
But, I'm using MySQL 8.x and it doesn't support this function.
I'm sorry, but SQL fiddle doesn't provide correct text-value for variables in my code :(
https://www.db-fiddle.com/f/wHanqoSCHKJHus5u6BU4DB/4
Or, you can see mistakes here:
SET #history_subscription_status = NULL;
SET #history_subscription_id = 0;
SELECT
c.date,
c.user_id,
c.subscription_id,
sd.subscription_status,
(#history_subscription_id := c.subscription_id) as 'historical_sub_id',
(#history_subscription_status := CASE
WHEN #history_subscription_id = c.subscription_id AND sd.subscription_status IS NULL
THEN #history_subscription_status
ELSE
sd.subscription_status
END
) as 'historical'
FROM
calendar c
LEFT JOIN
subscription_data sd ON sd.date = c.date AND sd.user_id = c.user_id AND sd.subscription_id = c.subscription_id
ORDER BY
c.user_id,
c.subscription_id,
c.date
I expect to get results for this query in this way:
IMPORTANT: I'm going to use this code for a lot of data (about 1 mln rows), so it very important for me to avoid additional select or subquery that can slow down the execution of the query.
In MySQL, is there a way to set the "total" fields to zero if they are NULL?
Here is what I have:
SELECT uo.order_id, uo.order_total, uo.order_status,
(SELECT SUM(uop.price * uop.qty)
FROM uc_order_products uop
WHERE uo.order_id = uop.order_id
) AS products_subtotal,
(SELECT SUM(upr.amount)
FROM uc_payment_receipts upr
WHERE uo.order_id = upr.order_id
) AS payment_received,
(SELECT SUM(uoli.amount)
FROM uc_order_line_items uoli
WHERE uo.order_id = uoli.order_id
) AS line_item_subtotal
FROM uc_orders uo
WHERE uo.order_status NOT IN ("future", "canceled")
AND uo.uid = 4172;
The data comes out fine, except the NULL fields should be 0.
How can I return 0 for NULL in MySQL?
Use IFNULL:
IFNULL(expr1, 0)
From the documentation:
If expr1 is not NULL, IFNULL() returns expr1; otherwise it returns expr2. IFNULL() returns a numeric or string value, depending on the context in which it is used.
You can use coalesce(column_name,0) instead of just column_name. The coalesce function returns the first non-NULL value in the list.
I should mention that per-row functions like this are usually problematic for scalability. If you think your database may get to be a decent size, it's often better to use extra columns and triggers to move the cost from the select to the insert/update.
This amortises the cost assuming your database is read more often than written (and most of them are).
None of the above answers were complete for me.
If your field is named field, so the selector should be the following one:
IFNULL(`field`,0) AS field
For example in a SELECT query:
SELECT IFNULL(`field`,0) AS field, `otherfield` FROM `mytable`
Hope this can help someone to not waste time.
You can try something like this
IFNULL(NULLIF(X, '' ), 0)
Attribute X is assumed to be empty if it is an empty String, so after that you can declare as a zero instead of last value. In another case, it would remain its original value.
Anyway, just to give another way to do that.
Yes IFNULL function will be working to achieve your desired result.
SELECT uo.order_id, uo.order_total, uo.order_status,
(SELECT IFNULL(SUM(uop.price * uop.qty),0)
FROM uc_order_products uop
WHERE uo.order_id = uop.order_id
) AS products_subtotal,
(SELECT IFNULL(SUM(upr.amount),0)
FROM uc_payment_receipts upr
WHERE uo.order_id = upr.order_id
) AS payment_received,
(SELECT IFNULL(SUM(uoli.amount),0)
FROM uc_order_line_items uoli
WHERE uo.order_id = uoli.order_id
) AS line_item_subtotal
FROM uc_orders uo
WHERE uo.order_status NOT IN ("future", "canceled")
AND uo.uid = 4172;
This request returns Else result
"ELSE RESULT" even if the condition is true.
SELECT
IF(Print_Server_Type='BW',SUM(Total_Impressions_Printed),'ELSE RESULT') AS BWTotalImpressions
FROM printedjob
WHERE
Account=''
And Job_Submission_Date>="2015-08-24"
AND Job_Submission_Date<="2015-08-28";
Same request with the where condition that works fine
SELECT
SUM(Total_Impressions_Printed) AS BWTotalImpressions
FROM printedjob
WHERE
Account=''
And Print_Server_Type='BW'
And Job_Submission_Date>="2015-08-24"
AND Job_Submission_Date<="2015-08-28";
I'm using the first request because I need the result to be a column from a select.
You are mixing aggregate terms (like SUM(Total_Impressions_Printed)) and single-row terms (like Print_Server_Type). Seems like you're trying to return a row per value of Print_Server_Type, which means you're missing a group by clause:
SELECT Print_Server_Type,
IF(Print_Server_Type = 'BW',
SUM(Total_Impressions_Printed),
'ELSE RESULT') AS BWTotalImpressions
FROM printedjob
WHERE Account = '' AND
Job_Submission_Date >= "2015-08-24" AND
Job_Submission_Date <= "2015-08-28"
GROUP BY Print_Server_Type
I think that your ELSE statement is written incorrectly. The else shouldn't be into quotes 'ELSE RESULT'... I would start by verifying to correct format to write the query.
Fixed the issue , here is the request:
Select Account,SUM(Total_Impressions),SUM(BWTotalImpressions)
FROM (
SELECT Account,Print_Server_Type,SUM(Total_Impressions_Printed) As Total_Impressions,
IF(Print_Server_Type='Color',SUM(Total_Color_Pages_Printed),'') AS ColorTotalImpressions,
IF(Print_Server_Type='BW',SUM(Total_Impressions_Printed),
IF(Print_Server_Type='Color',SUM(Total_Black_Only_Pages_Printed),'')) AS BWTotalImpressions
FROM printedjob
WHERE Job_Submission_Date>="2015-08-24" AND Job_Submission_Date<="2015-08-28"
GROUP BY Account,Print_Server_Type
)AS T
GROUP by Account;