Mysql Substract two columns based on greater than condition - mysql

I am doing substraction from TotalAmt to NetTotal but when TotalAmt is Less than NetTotal then Due is Showing Negative values.How do i display Due as zeros if TotalAmt is Less than NetTotal.My Query for retrieving Due amount is
SELECT DISTINCT id,
name,
TotalAmt,
NetTotal,
Due
FROM
(SELECT u.id,
u.name,
(SELECT SUM(amt)
FROM pay_master
WHERE refsid = u.id
AND typ IN ('std_deposit',
'sale_ind')
GROUP BY refsid) AS 'TotalAmt',
(SELECT IFNULL(SUM(net_total), 0)
FROM trans_master t
WHERE t.refid = u.id
GROUP BY t.refid) AS 'NetTotal',
IFNULL(
(SELECT IFNULL(SUM(amt), 0)
FROM pay_master p
WHERE p.refsid = u.id
AND typ IN ('std_deposit', 'sale_ind')
GROUP BY refsid) -
( SELECT IFNULL(SUM(net_total), 0)
FROM trans_master t
WHERE t.refid = u.id
GROUP BY t.refid), 0) AS 'Due'
FROM USER u
INNER
JOIN pay_master p ON p.refsid = u.id
AND u.typ = 'std')x

Are you looking for this??
SELECT DISTINCT id,
name,
TotalAmt,
NetTotal,
case when Due < 0 then 0 else Due end
FROM
(SELECT u.id,
u.name,
(SELECT SUM( amt )
FROM pay_master
WHERE refsid = u.id
AND typ IN ( 'std_deposit', 'sale_ind')
GROUP BY refsid
) AS 'TotalAmt',
(SELECT IFNULL( SUM( net_total ) , 0 )
FROM trans_master t
WHERE t.refid = u.id
GROUP BY t.refid
) AS 'NetTotal',
IFNULL(
(SELECT IFNULL( SUM( amt ) , 0 )
FROM pay_master p
WHERE p.refsid = u.id
AND typ IN ( 'std_deposit', 'sale_ind')
GROUP BY refsid
) -
(SELECT IFNULL( SUM( net_total ) , 0 )
FROM trans_master t
WHERE t.refid = u.id
GROUP BY t.refid
) , 0) AS 'Due'
FROM USER u
INNER JOIN pay_master p
ON p.refsid = u.id
AND u.typ = 'std'
)x
Use case to maintain for such of condition

Related

mysql : query three times on the same table

I am currently writing a query.
Retrieves information from users, posts, and additional information tables in posts (post_views_info).
SELECT
u.email,
u.user_nm,
p.pid,
p.post_ttl,
p.date,
p.ref_level,
p.ref_origin,
p.ref_step,
date(p.date) = date(now()) AS is_today,
(SELECT category_path FROM post_category WHERE category_id = p.category_id) as category_full_path,
(SELECT COUNT(*) FROM post_status_info AS sub_i WHERE sub_i.pid = p.pid AND sub_i.status = 'A') AS recommendCount,
(SELECT COUNT(*) FROM post_status_info AS sub_i WHERE sub_i.pid = p.pid AND sub_i.status = 'B') AS oppositeCount,
(SELECT COUNT(*) FROM post_status_info AS sub_i WHERE sub_i.pid = p.pid AND sub_i.status = 'C') AS reportCount
FROM
(
SELECT *
FROM post as p
WHERE
p.is_enable = 1
ORDER BY
p.ref_origin DESC,
p.ref_step ASC
) as p,
user AS u
WHERE
p.uid = u.uid
ORDER BY
ref_origin DESC,
ref_step ASC
In the above query, we query the same table three times to get the number of posts 'A', 'B', 'C'.
To solve this problem, I changed the query as follows.
SELECT
u.email,
u.user_nm,
p.pid,
p.post_ttl,
p.date,
p.ref_level,
p.ref_origin,
psi.reportCount,
psi.recommendCount,
psi.oppositeCount,
p.ref_step,
date(p.date) = date(now()) AS is_today,
(SELECT category_path FROM post_category WHERE category_id = p.category_id) as category_full_path
FROM
user AS u,
(
SELECT *
FROM post as p
WHERE
p.is_enable = 1
ORDER BY
p.ref_origin DESC,
p.ref_step ASC
LIMIT 0, 15
) as p left join
(
SELECT
pid,
COUNT(if(status = 'A', 1, null)) AS reportCount,
COUNT(if(status = 'B', 1, null)) AS recommendCount,
COUNT(if(status = 'C', 1, null)) AS oppositeCount
FROM post_status_info
group by pid
) AS psi
on
psi.pid = p.pid
WHERE
p.uid = u.uid
ORDER BY
ref_origin DESC,
ref_step ASC
I think it would be better to query the same table three times.
Which code is better in terms of performance?
Thanks.
I think second option is more fruitful in terms of performance. Because here we have less number of queries to execute.
You can also do it by using CASE.
SELECT
u.email,
u.user_nm,
p.pid,
p.post_ttl,
p.date,
p.ref_level,
p.ref_origin,
p.ref_step,
date(p.date) = date(now()) AS is_today,
(SELECT category_path FROM post_category WHERE category_id = p.category_id) as category_full_path,
(SUM(CASE WHEN sub_i.status = 'A' THEN 1 ELSE 0 END)) AS recommendCount,
(SUM(CASE WHEN sub_i.status = 'B' THEN 1 ELSE 0 END)) AS oppositeCount,
(SUM(CASE WHEN sub_i.status = 'C' THEN 1 ELSE 0 END)) AS reportCount
FROM
(
SELECT *
FROM post as p
WHERE
p.is_enable = 1
ORDER BY
p.ref_origin DESC,
p.ref_step ASC
) as p,
INNER JOIN user AS u ON u.uid = p.uid
INNER JOIN post_status_info as sub_i ON p.pid = sub_i.pid
GROUP BY p.pid
ORDER BY
ref_origin DESC,
ref_step ASC

How to create codeigniter query from below sql query?

I've a query like this which is working fine but I want to create a pure CI query from this. I'm new in CI so can anyone help me to figure out how this can be done or suggest me a reference website or link from where i can get help. Thanks
SELECT
user_des,
IFNULL((sent),0) as sent,
IFNULL((viewed),0) as viewed,
CONCAT(IFNULL(fname_usr,user_des),' ',lname_usr,user_des) as fullname,
IFNULL(sum(duration),0) as totalviewtime,
IFNULL((totalviews),0) as views,
IFNULL(sum(sharedcount),0) as shares,
IFNULL(sum(shared),0) as shared
FROM dem_senddemo
INNER JOIN
(SELECT * FROM dem_demos WHERE id_dem IN (746,943,748) AND customer_dem = '1') as demosfiltered
ON demo_des = id_dem
LEFT JOIN
(
(
Select senddemo_wis, sum(duration) as duration, max(datereceived_wis) as datereceived_wis
FROM
(
select senddemo_wis, invited_wis, sum(IFNULL(duration_fea,0) * IFNULL(percentviewed_wis,0)) as duration, max(datereceived_wis) as datereceived_wis
FROM (sta_views
LEFT JOIN sta_featureswisitavisits as s ON visit_fvi = id_vis
LEFT JOIN
(
(SELECT shortvideovid_fea as videoid_fea, shortvideoduration_fea as duration_fea
FROM dem_features
where shortvideoduration_fea > 0)
UNION
(SELECT longvideovid_fea as videoid_fea, longvideoduration_fea as duration_fea
FROM dem_features
where longvideoduration_fea > 0)
) as x
ON videoid_fea = showedvideo_fvi)
LEFT JOIN
sta_wistia as w ON invited_fvi = invited_wis AND s.showedvideo_fvi = w.mediaid_wis AND wistia_vis = email_wis
WHERE countvisit_wis <> 'N'
GROUP BY invited_wis
) as durfea
GROUP BY senddemo_wis
) UNION
(
SELECT senddemo_wis,sum(IFNULL(mainvideoduration_dem ,0) * IFNULL(percentviewed_wis,0)) as duration, max(datereceived_wis) as datereceived_wis
FROM sta_wistia as w
INNER JOIN
(select *, customer_dem as cuss FROM dem_demos) as demcorp ON demo_wis = id_dem AND mainmessagingvideovid_dem = w.mediaid_wis
LEFT JOIN sta_views ON email_wis = wistia_vis
WHERE customer_dem = 1 AND senddemo_wis > 0 AND countvisit_wis <> 'N'
GROUP BY senddemo_wis
)
) as c ON id_des = senddemo_wis
LEFT JOIN
(
SELECT user_des as user2_des, count(id_vis) as totalviews
FROM sta_views
LEFT JOIN dem_invited ON id_invited = invited_vis
LEFT JOIN dem_senddemo ON id_des = id_senddemo
WHERE NOT ISNULL(id_senddemo) AND countvisit_wis != 'N' AND createdon_des BETWEEN '2015-05-31 00:00:00' AND '2015-06-29 23:59:59' AND demo_des IN (746,943,748)
GROUP BY user_des
) as z ON user_des = user2_des
LEFT JOIN
(
SELECT user_des as user3_des, count(id_des) as sent
FROM dem_senddemo
LEFT JOIN dem_invited ON id_senddemo = id_des
WHERE createdon_des BETWEEN '2015-05-31 00:00:00' AND '2015-06-29 23:59:59' AND demo_des IN (746,943,748) AND first_invited = 'YES'
GROUP BY user_des
) as za ON user_des = user3_des
LEFT JOIN
(
SELECT user_des as user4_des, count(id_vis) as viewed
FROM sta_views LEFT JOIN dem_invited ON id_invited = invited_vis
LEFT JOIN dem_senddemo ON id_des = id_senddemo
WHERE NOT ISNULL(id_senddemo) AND countvisit_wis != 'N' AND createdon_des BETWEEN '2015-05-31 00:00:00' AND '2015-06-29 23:59:59' AND state = 'VIEWED'
AND first_invited = 'YES' AND demo_des IN (746,943,748)
GROUP BY user_des
) as zb ON user_des = user4_des
LEFT JOIN
(
SELECT id_senddemo as iddemdemos2, count(id_senddemo) as shared, allshares as sharedcount
FROM
(
SELECT id_senddemo, count(id_senddemo) as allshares
FROM dem_invited
LEFT JOIN dem_senddemo on id_senddemo = id_des
WHERE first_invited <> 'YES' AND demo_des IN (746,943,748)
GROUP BY id_senddemo
) as x
GROUP BY id_senddemo
) as zc ON iddemdemos2 = id_des
LEFT JOIN
sec_users ON user_des = id_usr
WHERE customer_dem = 1 AND createdon_des BETWEEN '2015-05-31 00:00:00' AND '2015-06-29 23:59:59'
GROUP BY user_des

MySQL: Grouped by hour, need to show all hours, null where no data

Here's the query:
SELECT h.idhour, h.`hour`, outnumber, count(*) as `count`, sum(talktime) as `duration`
FROM (
SELECT
`cdrs`.`dcustomer` AS `dcustomer`,
(CASE
WHEN (`cdrs`.`cnumber` like "02%") THEN '02'
WHEN (`cdrs`.`cnumber` like "05%") THEN '05'
END) AS `outnumber`,
FROM_UNIXTIME(`cdrs`.`start`) AS `start`,
(`cdrs`.`end` - `cdrs`.`start`) AS `duration`,
`cdrs`.`talktime` AS `talktime`
FROM `cdrs`
WHERE `cdrs`.`start` >= #_START and `cdrs`.`start` < #_END
AND `cdrs`.`dtype` = _LATIN1'external'
GROUP BY callid
) cdr
JOIN customers c ON c.id = cdr.dcustomer
LEFT JOIN hub.hours h ON HOUR(cdr.`start`) = h.idhour
WHERE (c.parent = _ID or cdr.dcustomer = _ID or c.parent IN
(SELECT id FROM customers WHERE parent = _ID))
GROUP BY h.idhour, cdr.outnumber
ORDER BY h.idhour;
The above query results skips the hours where there is no data, but I need to show all hours (00:00 to 23:00) with null or 0 values. How can I do this?
SELECT h.idhour
, h.hour
,IFNULL(outnumber,'') AS outnumber
,IFNULL(cdr2.duration,0) AS duration
,IFNULL(output_count,0) AS output_count
FROM hub.hours h
LEFT JOIN (
SELECT HOUR(start) AS start,outnumber, SUM(talktime) as duration ,COUNT(1) AS output_count
FROM
(
SELECT cdrs.dcustomer AS dcustomer
, (CASE WHEN (cdrs.cnumber like "02%") THEN '02' WHEN (cdrs.cnumber like "05%") THEN '05' END) AS outnumber
, FROM_UNIXTIME(cdrs.start) AS start
, (cdrs.end - cdrs.start) AS duration
, cdrs.talktime AS talktime
FROM cdrs cdrs
INNER JOIN customers c ON c.id = cdrs.dcustomer
WHERE cdrs.start >= #_START and cdrs.start < #_END AND cdrs.dtype = _LATIN1'external'
AND
(c.parent = _ID or cdrs.dcustomer = _ID or c.parent IN (SELECT id FROM customers WHERE parent = _ID))
GROUP BY callid
) cdr
GROUP BY HOUR(start),outnumber
) cdr2
ON cdr2.start = h.idhour
ORDER BY h.idhour
You need a table with all hours, nothing else.
Then use LEFT JOIN with the hours table on the "left" and your current query on the "right":
SELECT b.*
FROM hours h
LEFT JOIN ( ... ) b ON b.hr = h.hr
WHERE h.hr BETWEEN ... AND ...
ORDER BY hr;
Any missing hours will be NULLs in b.*.

How to join 2 queries

I have 2 SQL queries:
SELECT accounts.assigned_user_id, jt0.user_name assigned_user_name,
SUM( IF(opp.opportunity_type='2', IFNULL(opp.amount,0), 0) ) AS amt_revenue,
SUM( IF(opp.opportunity_type='4', IFNULL(opp.amount,0), 0) ) AS amt_return
FROM accounts
LEFT JOIN users jt0
ON jt0.id=accounts.assigned_user_id AND jt0.deleted=0 AND jt0.deleted=0
LEFT JOIN accounts_opportunities AS a_o
ON a_o.account_id = accounts.id AND a_o.deleted=0
LEFT JOIN opportunities AS opp
ON (opp.id = a_o.opportunity_id AND opp.deleted=0 AND opp.sales_stage = 'Closed Won' AND opp.opportunity_type IN('2', '4'))
WHERE accounts.deleted=0
GROUP BY accounts.assigned_user_id, jt0.user_name
ORDER BY SUM(IFNULL(opp.amount,0)) DESC
And:
SELECT accounts.assigned_user_id,
SUM( IFNULL(accounts_collections.amount,0)) AS amount
FROM accounts
LEFT JOIN accounts_collections ON(accounts_collections.account_id = accounts.id AND accounts_collections.deleted=0)
GROUP BY accounts.assigned_user_id
How can I join the 2 queries above?
You may be able to put the second query into a subselect. There are two ways of doing this. In the select section or in the form section. Not sure which MySQL accepts but both work in other SQL engines.
SELECT
accounts.assigned_user_id,
jt0.user_name assigned_user_name,
SUM( IF(opp.opportunity_type='2',
IFNULL(opp.amount,0), 0)
) AS amt_revenue,
SUM( IF(opp.opportunity_type='4',
IFNULL(opp.amount,0), 0)
) AS amt_return,
(
SELECT SUM( IFNULL(accounts_collections.amount,0)) AS amount
FROM accounts
LEFT JOIN accounts_collections ON(accounts_collections.account_id = accounts.id AND accounts_collections.deleted=0)
GROUP BY accounts.assigned_user_id
) AS amount
FROM accounts
LEFT JOIN users jt0
ON jt0.id=accounts.assigned_user_id AND jt0.deleted=0 AND jt0.deleted=0
LEFT JOIN accounts_opportunities AS a_o
ON a_o.account_id = accounts.id AND a_o.deleted=0
LEFT JOIN opportunities AS opp
ON (opp.id = a_o.opportunity_id AND opp.deleted=0 AND opp.sales_stage = 'Closed Won' AND opp.opportunity_type IN('2', '4'))
WHERE accounts.deleted=0
GROUP BY accounts.assigned_user_id, jt0.user_name
ORDER BY SUM(IFNULL(opp.amount,0)) DESC
SELECT
accounts.assigned_user_id,
jt0.user_name assigned_user_name,
SUM( IF(opp.opportunity_type='2',
IFNULL(opp.amount,0), 0)
) AS amt_revenue,
SUM( IF(opp.opportunity_type='4',
IFNULL(opp.amount,0), 0)
) AS amt_return,
amount_tbl.amount
FROM accounts
LEFT JOIN users jt0
ON jt0.id=accounts.assigned_user_id AND jt0.deleted=0 AND jt0.deleted=0
LEFT JOIN accounts_opportunities AS a_o
ON a_o.account_id = accounts.id AND a_o.deleted=0
LEFT JOIN opportunities AS opp
ON (opp.id = a_o.opportunity_id AND opp.deleted=0 AND opp.sales_stage = 'Closed Won' AND opp.opportunity_type IN('2', '4'))
JOIN (
SELECT accounts.assigned_user_id,
SUM( IFNULL(accounts_collections.amount,0)) AS amount
FROM accounts
LEFT JOIN accounts_collections ON(accounts_collections.account_id = accounts.id AND accounts_collections.deleted=0)
GROUP BY accounts.assigned_user_id
) AS amount_tbl ON (amount_tbl.assigned_user_id = accounts.assigned_user_id)
WHERE accounts.deleted=0
GROUP BY accounts.assigned_user_id, jt0.user_name
ORDER BY SUM(IFNULL(opp.amount,0)) DESC

How to improve cost of joined queries

I have a query in sql as below that takes 40 minutes to respond!
Any recommendations for tuning of this will be appreciated.
select
QA.*,
QB.Tedade_Forushe_Ensheab
from
( ( SELECT
dbo.MiladiTOShamsi(GETDATE()) AS CURENT_DATE,
'93/01/15' AS F_DATE,
'93/01/20' AS T_DATE,
E.title,
E.code as EsterCode,
SUM( dbo.fn_ShamsiDateStrDiffDay( R.req_date, M.install_date )) AS TOTAL_DAY,
COUNT(*) AS CNT,
COUNT(R.req_seq) AS Req_seq_Count,
SUM( dbo.fn_ShamsiDateStrDiffDay( R.req_date, R.actv_date )) / COUNT(*) AS AVR_1,
SUM( dbo.fn_ShamsiDateStrDiffDay( R.visit_date, R.actv_date )) / COUNT(*) AS AVR_2,
SUM( dbo.fn_ShamsiDateStrDiffDay( R.pay_date, R.actv_date )) / COUNT(*) AS AVR_3,
SUM( dbo.fn_ShamsiDateStrDiffDay( R.visit_date, R.pay_date )) / COUNT(*) AS AVR_4,
SUM( dbo.fn_ShamsiDateStrDiffDay( R.req_date, R.visit_date )) / COUNT(*) AS AVR_5,
SUM( dbo.fn_ShamsiDateStrDiffDay( R.req_date, R.pay_date )) / COUNT(*) AS AVR_6,
SUM( dbo.fn_ShamsiDateStrDiffDay( R.actv_date, R.create_actv_date )) / COUNT(*) AS AVR_7,
SUM( dbo.fn_ShamsiDateStrDiffDay( R.actv_date, M.first_date )) / COUNT(*) AS AVR_8
FROM
tby_1_request AS R
INNER JOIN y_1_tariff AS T
ON R.tariff_type = T.tariff
INNER JOIN tby_1_meter AS M
ON R.cust_id = M.cust_id
INNER JOIN tby_1_estr AS E
ON R.estr = E.code
WHERE
R.net_status = 3
AND R.actv_date >= '93/01/15'
AND R.actv_date <= '93/01/20'
AND R.pay_date >= '93/01/15'
AND R.pay_date <= '93/01/20'
GROUP BY
E.title,
E.code ) AS QA
left join
( Select
A.*,
B.Tedade_Forushe_Ensheab,
C.Tedade_Nasbfrom,
D.Tedade_ijade_sabegeh
from
( select distinct Estr.title
from tby_1_request Req
INNER JOIN tby_1_estr AS Estr
ON Req.estr = Estr.code
INNER JOIN y_1_tariff AS T
ON Req.tariff_type = T.tariff
INNER JOIN tby_1_meter AS M
ON Req.cust_id = M.cust_id
group by
Estr.title,
Estr.code,
Req.pay_date,
Req.net_status,
Req.actv_date
having
Req.net_status = 3
AND Req.actv_date >= '93/01/15'
AND Req.actv_date <= '93/01/20'
AND Req.pay_date >= '93/01/15'
AND Req.pay_date <= '93/01/20' ) AS A
left join
( select
Estr.title,
COUNT( CASE WHEN Pay_date IS NOT NULL AND Req.pay_date >= '93/01/15' AND Req.pay_date <= '93/01/20'
THEN 1 ELSE NULL END) AS Tedade_Forushe_Ensheab
from
tby_1_request Req
INNER JOIN tby_1_estr AS Estr
ON Req.estr = Estr.code
group by
Estr.title,
Estr.code) AS B
ON A.title = B.title
left join
( select
Estr.title,
COUNT( CASE WHEN actv_date IS NOT NULL AND Req.actv_date >= '93/01/15' AND Req.actv_date <= '93/01/20'
THEN 1 ELSE NULL END) AS Tedade_Nasbfrom
from
tby_1_request Req
INNER JOIN tby_1_estr AS Estr
ON Req.estr = Estr.code
group by
Estr.title,
Estr.code ) AS C
ON A.title = C.title
left join
( select
Estr.title,
COUNT( CASE WHEN create_actv_date IS NOT NULL AND Req.create_actv_date >= '93/01/15' AND Req.create_actv_date <= '93/01/20'
THEN 1 ELSE NULL END ) AS Tedade_ijade_sabegeh
from
tby_1_request Req
INNER JOIN tby_1_estr AS Estr
ON Req.estr = Estr.code
group by
Estr.title,
Estr.code ) AS D
ON A.title = D.title ) AS QB
On QA.title = Qb.title
I edited your original SQL query for readability purposes only. I re-adjusted, appeared to miss a double open paren for inner A-D left-join queries.
Additionally, without knowing table structures or available indexes, I would ensure on your tby_1_request table, you have an index on ( net_status, actv_date, pay_date ) to help on your WHERE criteria. Also, for your B, C and D queries for counts, I would have individual indexes on (pay_date, estr), (actv_date, estr), and (create_actv_date, estr)
Looking a little closer, you are also getting a Cartesian result which is probably killing you as your queries are all grouped by title and code, but you are only joining on the title column.