return 0 if a value is null - php

I have a MySQL query in my php script, which is working fine currently. The only issue I have is that some of the columns return null values.
If there is data for those columns then they return the value, but if there is no data or records for the date then they return null. All I want to do is modify this query so that if anything is null it returns '0'.
I'm not sure if I should use IFNULL or coalesce but either way I'm unfamiliar with the best way to apply it to this query.
Any help is much appreciated.
$stmt3 = mysqli_prepare($conn2,
"UPDATE ambition.ambition_totals a
INNER JOIN
(SELECT
c.user AS UserID,
COUNT(*) AS dealers,
ROUND((al.NumberOfDealers / al.NumberOfDealerContacts) * 100 ,2) AS percent
FROM jfi_dealers.contact_events c
JOIN jackson_id.users u
ON c.user = u.id
JOIN jfi_dealers.dealers d
ON c.dealer_num = d.dealer_num
LEFT JOIN (
SELECT user_id, COUNT(*) AS NumberOfDealerContacts,
SUM(CASE WHEN ( d.next_call_date + INTERVAL 7 DAY) THEN 1 ELSE 0 END) AS NumberOfDealers
FROM jackson_id.attr_list AS al
JOIN jfi_dealers.dealers AS d ON d.csr = al.data
WHERE al.attr_id = 14
GROUP BY user_id) AS al
ON al.user_id = c.user
GROUP BY UserID) as cu
on cu.UserID = a.ext_id
SET a.dealers_contacted = cu.dealers,
a.percent_up_to_date = cu.percent;
") or die(mysqli_error($conn2));
UPDATE
Version with IFNULL statment:
UPDATE ambition.ambition_totals a
INNER JOIN
(SELECT
c.user AS UserID,
ifnull(count(*),0) AS dealers,
ifnull(ROUND((al.NumberOfDealers / al.NumberOfDealerContacts) * 100 ,2),0) AS percent
FROM jfi_dealers.contact_events c
JOIN jackson_id.users u
ON c.user = u.id
JOIN jfi_dealers.dealers d
ON c.dealer_num = d.dealer_num
LEFT JOIN (
SELECT user_id, COUNT(*) AS NumberOfDealerContacts,
SUM(CASE WHEN ( d.next_call_date + INTERVAL 7 DAY) THEN 1 ELSE 0 END) AS NumberOfDealers
FROM jackson_id.attr_list AS al
JOIN jfi_dealers.dealers AS d ON d.csr = al.data
WHERE al.attr_id = 14
GROUP BY user_id) AS al
ON al.user_id = c.user
WHERE c.created_at >= CURDATE()
GROUP BY UserID) as cu
on cu.UserID = a.ext_id
SET a.dealers_contacted = cu.dealers,
a.percent_up_to_date = cu.percent;

Yes, you can use IFNULL for this. But be very sure that you actually want this behaviour. PHP is also familiar with NULL values and can handle them just fine. 0 has a very different meaning. But if you do want this behaviour, simply wrap the field or statement that might return null in a IFNULL, for example:
SELECT IFNULL(user_id, 0);
But you can also do this in PHP itself, so you do not have to modify the query:
if (is_null($result['field'])) {
echo 0;
}
Or, if you use PHP 7+, you can also use the null coalescing operator:
echo $result['field'] ?? 0;

Related

Duplicate MethodID in query

I have a query that is using a subquery, and I can't seem to figure out why it is telling me I have duplicate methodID's. The query is supposed to take the data and order by and group by for showing only the latest single result for a given studentID where there could be multiple results with different timestamps but same studentID
SELECT a.*
FROM
( SELECT *
, o.methodName oldName
, n.methodName newName
, s.firstName fName
, s.lastName lName
FROM changeReport r
LEFT
JOIN methodLookup o
ON o.methodID = r.oldMethod
LEFT
JOIN methodLookup n
ON n.methodID = r.newMethod
JOIN students s
ON s.studentID = r.studentID
LEFT
JOIN staffaccounts a
ON r.staffID = a.staffID
WHERE 31 IN (newSubMethod,oldSubMethod)
AND date(timestamp) = CURRENT_DATE
) a
JOIN
( SELECT students.studentID
, MAX(timestamp) timestamp
FROM changeReport r
LEFT
JOIN methodLookup o
ON o.methodID = r.oldMethod
LEFT
JOIN methodLookup n
ON n.methodID = r.newMethod
JOIN students s
ON s.studentID = r.studentID
LEFT
JOIN staffaccounts a
ON r.staffID = a.staffID
WHERE 31 IN (newSubMethod,oldSubMethod)
AND date(timestamp) = CURRENT_DATE
) b
ON b.studentID = a.studentID
AND b.timestamp = a.timestamp;
Any ideas on how this could be?

simplify this SQL request

I have this sql request :
SELECT pl.*, l.loyer, l.charges, l.locataire_id, laire.nom, laire.prenom,
l.chambre_id, c.numero, c.etage, c.maison_id, m.titre_crm
FROM
(
SELECT spl.id, spl.location_id, spl.mois, spl.annee, spl.loyer_paye
from locations sl
LEFT JOIN
(
SELECT * FROM paiement_loyer
union
SELECT 9999, usl.id, (MONTH(NOW())-1), YEAR(NOW()), 0
FROM locations usl
WHERE usl.id not in (SELECT location_id FROM paiement_loyer) ||
(select count(*) FROM paiement_loyer
WHERE location_id = usl.id AND annee = YEAR(NOW())
AND mois=(MONTH(NOW())-1) ) = 0
) spl ON sl.id = spl.location_id
where sl.date_debut <= CURDATE() && CURDATE() <= sl.date_fin
) pl
JOIN locations l ON pl.location_id = l.id
JOIN locataires laire ON l.locataire_id = laire.id
JOIN chambres c ON l.chambre_id = c.id
JOIN maisons m ON c.maison_id = m.id
ORDER BY trim(upper(m.titre_crm)), c.numero, annee, mois
I would like to simplify it, do you have any idea please ?
An attempt at cleaning it up. Note that I think the first LEFT OUTER JOIN could probably be swapped to an INNER JOIN.
I have swapped the 2nd UNIONed query to 2 queries, and for those I have changed them to use LEFT OUTER JOINs which then check that there isn't a match
SELECT pl.id, pl.location_id, pl.mois, pl.annee, pl.loyer_paye,
l.loyer, l.charges, l.locataire_id, laire.nom, laire.prenom,
l.chambre_id, c.numero, c.etage, c.maison_id, m.titre_crm
FROM
(
SELECT spl.id, spl.location_id, spl.mois, spl.annee, spl.loyer_paye
FROM locations sl
LEFT OUTER JOIN
(
SELECT id, location_id, mois, annee, loyer_paye
FROM paiement_loyer
UNION
SELECT 9999, usl.id, (MONTH(NOW())-1), YEAR(NOW()), 0
FROM locations usl
LEFT OUTER JOIN paiement_loyer pl1
ON usl.id = pl1.location_id
WHERE pl1.location_id IS NULL
SELECT 9999, usl.id, (MONTH(NOW())-1), YEAR(NOW()), 0
FROM locations usl
LEFT OUTER JOIN paiement_loyer pl2
ON usl.id = pl1.location_id
AND pl2.annee = YEAR(NOW())
AND pl2.mois=(MONTH(NOW())-1)
WHERE pl2.location_id IS NULL
) spl ON sl.id = spl.location_id
WHERE CURDATE() BETWEEN sl.date_debut AND sl.date_fin
) pl
JOIN locations l ON pl.location_id = l.id
JOIN locataires laire ON l.locataire_id = laire.id
JOIN chambres c ON l.chambre_id = c.id
JOIN maisons m ON c.maison_id = m.id
ORDER BY TRIM(UPPER(m.titre_crm)), c.numero, pl.annee, pl.mois

count clause to output all records in database - mysql

I been trying different combination, but I cant seems to get this to work. I have inner join tables, I want to count the number of QA ISSUE found in the records and also output those records with only QA ISSUE, How would I do that?
SELECT d.department, m.mo_number, m.part_number, c.category,
COUNT(CASE WHEN c.category = 'QA ISSUE' THEN category END) as qa_issue,
SUM(CASE WHEN c.category = 'QA ISSUE' THEN time_spent END) as time_spent
FROM master as m
INNER JOIN category as c ON c.cat_id = m.cat_id
INNER JOIN department as d ON d.dept_id = m.dept_id
WHERE m.date_created >= DATE_SUB(now(), INTERVAL 50 DAY) AND
d.department = 'Electronics'
GROUP BY m.mo_number
ORDER BY 1
To filter results by aggregates you use the HAVING clause which occurs after the GROUP BY clause. Note this is not a substitute for the WHERE clause (which chooses the rows to be aggregated).
SELECT
d.department
, m.mo_number
, m.part_number
, c.category
, COUNT(*) AS qa_issue
, SUM(time_spent) AS time_spent
FROM master AS m
INNER JOIN category AS c ON c.cat_id = m.cat_id
INNER JOIN department AS d ON d.dept_id = m.dept_id
WHERE m.date_created >= DATE_SUB(now(), INTERVAL 50 DAY)
AND d.department = 'Electronics'
AND c.category = 'QA ISSUE'
GROUP BY
d.department
, m.mo_number
, m.part_number
, c.category
HAVING COUNT(*) = 1
ORDER BY
d.department
I have also added a condition to the where clause and added all non-aggregated columns into the GROUP BY clause - which I recommend you do always.

How to count records as per all year?

I need to count record year wise, I did some query but i am not getting correct result. Below is my query. But that is not working for me. Can anyone please look in this and give me right query ? Any help will be appreciated.
SELECT
(SELECT count(DISTINCT id) FROM call_response WHERE disposition=0 AND user_id=pu.id ) AS `trueAlarm`,
(SELECT count(DISTINCT id) FROM call_response WHERE disposition=1 AND user_id=pu.id ) AS `falseAlarm`,
(SELECT count(DISTINCT id) FROM call_response WHERE disposition=2 AND user_id=pu.id ) AS `disregarded`,
YEAR(cr.created_date) AS `callYear`
FROM `call_response` AS `cr`
INNER JOIN `permit_users` AS `pu`
ON cr.user_id=pu.id
WHERE ( pu.is_deleted=0 AND pu.is_trashed=0 AND cr.is_deleted=0)
GROUP BY `callYear`
The query that you want uses either conditional aggregation or subqueries, but not both. In other words, either use the subqueries but do not have an outer join to call_response. Or, have the outer join but not the subqueries.
I would write the query like this:
SELECT count(distinct case when disposition = 0 AND user_id = pu.id then id end) as trueAlarm,
count(distinct case when disposition = 1 AND user_id = pu.id then id end) as falseAlarm,
count(distinct case when disposition = 2 AND user_id = pu.id then id end) as disregarded,
YEAR(cr.created_date) AS `callYear`
FROM `call_response` `cr` INNER JOIN
`permit_users` `pu`
ON cr.user_id = pu.id
WHERE pu.is_deleted = 0 AND pu.is_trashed = 0 AND cr.is_deleted = 0
GROUP BY `callYear`;

How Can i Convert this multiple sub query in zend query?

i have the following query which gives desired output in mysql , now i want to implement it in zend query language,
which has different approach to implement the query..
SELECT A.NAME , B.PAYMENT , C.TOTALPROJ , D.TOTALTASK , T.ACTIVETASK , H.HOUR
FROM USERMASTER AS A
LEFT OUTER JOIN
(
SELECT A.U_ID , SUM(A.TOTALTIME * B.RATE) AS PAYMENT
FROM
(
SELECT U_ID , PROJECT_ID ,
SUM(TIME_TO_SEC(CASE WHEN endtime is null then timediff (starttime,starttime)
ELSE timediff (endtime,starttime) END )) / 3600 AS TOTALTIME
FROM LOGMASTER AS A
WHERE PROJECT_ID IS NOT NULL
GROUP BY U_ID , PROJECT_ID
) AS A
INNER JOIN PROJECTTOUSER AS B ON A.PROJECT_ID = B.PROJECT_ID AND A.U_ID = B.U_ID
GROUP BY B.U_ID
) AS B ON A.ID = B.U_ID
LEFT OUTER JOIN
(
SELECT U_ID , COUNT(*) AS TOTALPROJ FROM PROJECTTOUSER GROUP BY U_ID
) AS C ON A.ID = C.U_ID
LEFT OUTER JOIN
(
SELECT ASSIGNED_TO , COUNT(*) AS TOTALTASK FROM TASKTOTARGET GROUP BY ASSIGNED_TO
) AS D ON A.ID = D.ASSIGNED_TO
LEFT OUTER JOIN
(
SELECT ASSIGNED_TO,COUNT(*) AS ACTIVETASK FROM TASKTOTARGET WHERE
IS_ACTIVE = 0 GROUP BY ASSIGNED_TO
) AS T ON A.ID = T.ASSIGNED_TO
LEFT OUTER JOIN
(
SELECT U_ID, SEC_TO_TIME(SUM(TIME_TO_SEC(CASE WHEN endtime is null then
timediff (starttime,starttime) ELSE timediff (endtime,starttime) END ))) AS HOUR
FROM LOGMASTER WHERE INSERT_DATE >= '2013-08-20' AND INSERT_DATE <='2013-08-31'
GROUP BY U_ID
) AS H ON A.ID = H.U_ID
so if any one can guide me in how to create this query in zend then it will be very helpful, and appreciated
Each of your subqueries becomes an new Zend_Query that you can then use just like a table and pass in to the main query.
For example:
$h = new Zend_Db_Select()
->from('LOGMASTER', array('U_ID', 'HOUR' => new Zend_Db_Expr('SEC_TO_TIME(SUM(TIME_TO_SEC(CASE WHEN endtime is null then
timediff (starttime,starttime) ELSE timediff (endtime,starttime) END ))))')
->where("INSERT_DATE >= '2013-08-20'")
->where("INSERT_DATE <= '2013-08-31'")
->group('U_ID');
$mainQuery = new Zend_Db_Select()
->from('a' => 'USERMASTER', array('NAME'))
->joinLeft($h, 'A.ID = H.U_IS', array('HOUR'));
You would create each of your subqueries as its own object and then you can join them into your main query. The last argument of the join function is which columns from the subquery should be added to the main query.
With ZF's fluid interface you can keep joining tables/queries until you have built your entire query.
http://framework.zend.com/manual/1.12/en/zend.db.select.html

Categories