mysql get rollup value - mysql

I want to ask about mysql with rollup only get rollup value, this is my code
SELECT tbldept.CodeDept AS Dept,
SUM(CASE WHEN tblemp.Status = '1' THEN 1 ELSE 0 END) AS headcount,
SUM(CASE WHEN tblemp.Status = '1' THEN 1 ELSE 0 END) * 144 AS RegHrsEst,
CONCAT(ROUND(20), '%') AS TargetOT,
round(SUM(CASE WHEN tblemp.Status = '1' THEN 1 ELSE 0 END) * 144 * 0.2) AS OTHrsBdgt
FROM tbldept
LEFT JOIN tblemp
ON tbldept.CodeDept = tblemp.CodeDept AND
tblemp.class = "DIR"
WHERE tbldept.CodeDept != 'FIN' AND
tbldept.CodeDept != 'HRT' AND
tbldept.CodeDept != 'ISD'
GROUP BY tbldept.CodeDept with ROLLUP;
result of rollup query:
how can i only get the rollup values? Thanks before

If you just want the row of rollup, simply use having:
SELECT tbldept.CodeDept AS Dept,
SUM(CASE WHEN tblemp.Status = '1' THEN 1 ELSE 0 END) AS headcount,
SUM(CASE WHEN tblemp.Status = '1' THEN 1 ELSE 0 END) * 144 AS RegHrsEst,
CONCAT(ROUND(20), '%') AS TargetOT,
round(SUM(CASE WHEN tblemp.Status = '1' THEN 1 ELSE 0 END) * 144 * 0.2) AS OTHrsBdgt
FROM tbldept
LEFT JOIN tblemp
ON tbldept.CodeDept = tblemp.CodeDept AND
tblemp.class = "DIR"
WHERE tbldept.CodeDept != 'FIN' AND
tbldept.CodeDept != 'HRT' AND
tbldept.CodeDept != 'ISD'
GROUP BY tbldept.CodeDept with ROLLUP
HAVING Dept IS NULL;
Edit:
having should work, check if there are some other reasons exist or not.
Or just wrap your query with a subquery:
SELECT *
FROM (
SELECT tbldept.CodeDept AS Dept,
SUM(CASE WHEN tblemp.Status = '1' THEN 1 ELSE 0 END) AS headcount,
SUM(CASE WHEN tblemp.Status = '1' THEN 1 ELSE 0 END) * 144 AS RegHrsEst,
CONCAT(ROUND(20), '%') AS TargetOT,
round(SUM(CASE WHEN tblemp.Status = '1' THEN 1 ELSE 0 END) * 144 * 0.2) AS OTHrsBdgt
FROM tbldept
LEFT JOIN tblemp
ON tbldept.CodeDept = tblemp.CodeDept AND
tblemp.class = "DIR"
WHERE tbldept.CodeDept != 'FIN' AND
tbldept.CodeDept != 'HRT' AND
tbldept.CodeDept != 'ISD'
GROUP BY tbldept.CodeDept with ROLLUP
) t
WHERE Dept IS NULL;

Related

sql How to hide row if entire row value is 0

My Query :
SELECT
(ref_intake.intakeno) AS intake,
SUM(CASE WHEN(student.intakeid AND student.status = '3' AND (student.courseid=3 OR student.courseid=17)) THEN 1 else 0 END) as active,
SUM(CASE WHEN(student.intakeid AND student.status = '5' AND (student.courseid=3 OR student.courseid=17)) THEN 1 else 0 END) as deffered,
SUM(CASE WHEN(student.intakeid AND student.status = '16' AND (student.courseid=3 OR student.courseid=17)) THEN 1 else 0 END) as inactive,
SUM(CASE WHEN(student.intakeid AND student.status = '9' AND (student.courseid=3 OR student.courseid=17)) THEN 1 else 0 END) as missing,
SUM(CASE WHEN(student.intakeid AND student.status = '6' AND (student.courseid=3 OR student.courseid=17)) THEN 1 else 0 END) as widthdrawn,
SUM(CASE WHEN(student.intakeid AND student.status IN (18,7,36) AND (student.courseid=3 OR student.courseid=17)) THEN 1 else 0 END) as dis_ter_dereg
FROM student
LEFT JOIN ref_intake ON student.intakeid = ref_intake.intakeid
GROUP BY student.intakeid ORDER BY ref_intake.intakeno ASC
The the image is my result:
I do suspect that your query can be simplified as follows:
SELECT
s.intakeid AS intake,
SUM(CASE WHEN s.status = 3 THEN 1 ELSE 0 END) as active,
SUM(CASE WHEN s.status = 5 THEN 1 ELSE 0 END) as deffered,
SUM(CASE WHEN s.status = 16 THEN 1 ELSE 0 END) as inactive,
SUM(CASE WHEN s.status = 9 THEN 1 ELSE 0 END) as missing,
SUM(CASE WHEN s.status = 6 THEN 1 ELSE 0 END) as widthdrawn,
SUM(CASE WHEN s.status IN (18, 7, 36) THEN 1 ELSE 0 END) as dis_ter_dereg
FROM student s
INNER JOIN ref_intake ri ON s.intakeid = ri.intakeid
WHERE
s.intakeid
AND s.status IN (3, 5, 16, 9, 6, 18, 7, 36)
AND s.courseid IN (3, 17)
GROUP BY s.intakeid
ORDER BY ri.intakeno ASC
That is:
most conditions can be moved to the WHERE clause - this should actually remove rows where no condition matches
it seems like you actually want an INNER JOIN rather than a LEFT JOIN - but you can revert that change if needed
table aliases make the query easier to read and write
ORed conditions can be simplified to use IN

MySql union Sum(Case())

How can I do a "union" in order to get only distinct values for "ACTIVITY" field, but with the variables started by "OUTPUT_" from "OUTPUT_TAB" appearing in the header. (Like "INPUT_" variables from "INPUT_TAB") .
It's possible ? I can not do it.
Check my Query PIC_QUERY:
SELECT
ACTIVIDADE,
SUM(CASE WHEN DATA_VAL_REGISTO = '2017-06-25' THEN 1 ELSE 0 END) INPUT_ACT_DATE_VOL,
SUM(CASE WHEN DATA_VAL_REGISTO = '2017-06-24' THEN 1 ELSE 0 END) PREV_DATE_VOL,
SUM(CASE WHEN WEEK(DATA_VAL_REGISTO,7) = '25' AND YEAR(DATA_VAL_REGISTO) = '2017' THEN 1 ELSE 0 END) INPUT_ACT_WEEK_VOL,
SUM(CASE WHEN WEEK(DATA_VAL_REGISTO,7) = '24' AND YEAR(DATA_VAL_REGISTO) = '2017' THEN 1 ELSE 0 END) INPUT_PREV_WEEK_VOL,
SUM(CASE WHEN MONTH(DATA_VAL_REGISTO) = '6' AND YEAR(DATA_VAL_REGISTO) = '2017' THEN 1 ELSE 0 END) INPUT_ACT_MONTH_VOL,
SUM(CASE WHEN MONTH(DATA_VAL_REGISTO) = '5' AND YEAR(DATA_VAL_REGISTO) = '2017' THEN 1 ELSE 0 END) INPUT_PREV_MONTH_VOL
FROM INPUT_TAB
GROUP BY ACTIVIDADE
UNION
SELECT
ACTIVIDADE,
SUM(CASE WHEN DATA_FIM_REP = '2017-06-25' THEN 1 ELSE 0 END) OUTPUT_ACT_DATE_VOL,
SUM(CASE WHEN DATA_FIM_REP = '2017-06-24' THEN 1 ELSE 0 END) OUTPUT_PREV_DATE_VOL,
SUM(CASE WHEN WEEK(DATA_FIM_REP,7) = '25' AND YEAR(DATA_FIM_REP) = '2017' THEN 1 ELSE 0 END) OUTPUT_ACT_WEEK_VOL,
SUM(CASE WHEN WEEK(DATA_FIM_REP,7) = '24' AND YEAR(DATA_FIM_REP) = '2017' THEN 1 ELSE 0 END) OUTPUT_PREV_WEEK_VOL,
SUM(CASE WHEN MONTH(DATA_FIM_REP) = '6' AND YEAR(DATA_FIM_REP) = '2017' THEN 1 ELSE 0 END) OUTPUT_ACT_MONTH_VOL,
SUM(CASE WHEN MONTH(DATA_FIM_REP) = '5' AND YEAR(DATA_FIM_REP) = '2017' THEN 1 ELSE 0 END) OUTPUT_PREV_MONTH_VOL
FROM OUTPUT_TAB
GROUP BY ACTIVIDADE
RESULT: PIC_RESULT
You don't want a union of two query results, but a join:
SELECT
actividade,
i.input_act_date_vol, i.input_prev_date_vol, i.input_act_week_vol,
i.input_prev_week_vol, i.input_act_month_vol, i.input_prev_month_vol,
o.output_act_date_vol, o.output_prev_date_vol, o.output_act_week_vol,
o.output_prev_week_vol, o.output_act_month_vol, o.output_prev_month_vol
FROM
(
SELECT
actividade,
SUM(data_val_registo = '2017-06-25') AS input_act_date_vol,
SUM(data_val_registo = '2017-06-24') AS input_prev_date_vol,
SUM(WEEK(data_val_registo, 7) = 25 AND YEAR(data_val_registo) = 2017) AS input_act_week_vol,
SUM(WEEK(data_val_registo, 7) = 24 AND YEAR(data_val_registo) = 2017) AS input_prev_week_vol,
SUM(MONTH(data_val_registo) = 6 AND YEAR(data_val_registo) = 2017) AS input_act_month_vol,
SUM(MONTH(data_val_registo) = 5 AND YEAR(data_val_registo) = 2017) AS input_prev_month_vol
FROM input_tab
GROUP BY actividade
) i
JOIN
(
SELECT
actividade,
SUM(data_fim_rep = '2017-06-25') AS output_act_date_vol,
SUM(data_fim_rep = '2017-06-24') AS output_prev_date_vol,
SUM(WEEK(data_fim_rep, 7) = 25 AND YEAR(data_fim_rep) = 2017) AS output_act_week_vol,
SUM(WEEK(data_fim_rep, 7) = 24 AND YEAR(data_fim_rep) = 2017) AS output_prev_week_vol,
SUM(MONTH(data_fim_rep) = 6 AND YEAR(data_fim_rep) = 2017) AS output_act_month_vol,
SUM(MONTH(data_fim_rep) = 5 AND YEAR(data_fim_rep) = 2017) ASoutput_prev_month_vol
FROM OUTPUT_TAB
GROUP BY actividade
) o USING (actividade);
In case there can be input without output or vice versa, you'll have to use an outer join instead. In case there can even be both, input without output and output without input, you'll have to look up how to emulate a full outer join in MySQL.
I've removed CASE WHEN .. THEN 1 ELSE 0 END, because a boolean expression results in true or false which equal to 1 and 0 in MySQL.
BTW: As this is all about 2017, you can get your queries simpler and faster by using WHERE YEAR(data_val_registo) and WHERE YEAR(data_fim_rep) = 2017 and removing the condition from the sum expressions.

How to fetch data in one row using case condition

I have two tables and i wanted data should come in specific format.
My query
SELECT
DISTINCT ur.suid,
(CASE WHEN ur.sceneID = '1' THEN ur.data ELSE 0 END) AS Scenario1data,
(CASE WHEN ur.sceneID = '1' THEN ss.score ELSE 0 END) AS Scenario1score,
(CASE WHEN ur.sceneID = '2' THEN ur.data ELSE 0 END) AS Scenario2,
(CASE WHEN ur.sceneID = '3' THEN ur.data ELSE 0 END) AS Scenario3,
(CASE WHEN ur.sceneID = '4' THEN ur.data ELSE 0 END) AS Scenario4
FROM tbluserresults AS ur LEFT JOIN tbluserscenescores AS ss ON ss.suid = ur.suid;
Result i wanted
suid Scenario1data Scenario1score Scenario2 Scenario3 Scenario4
1 'abc show1' 334 abc show2 abc show3 abc show 4
2 0 0 0 0.
Check my SQLFIDDLE
There are probably other better ways to do this, but I believe the following does what you want
SELECT results.suid as suid,
(CASE WHEN results.Scenario1data IS NOT NULL THEN results.Scenario1data ELSE 0 END) AS Scenario1data,
(CASE WHEN results.Scenario1score IS NOT NULL THEN results.Scenario1score ELSE 0 END) AS Scenario1score,
(CASE WHEN results.Scenario2 IS NOT NULL THEN results.Scenario2 ELSE 0 END) AS Scenario2,
(CASE WHEN results.Scenario3 IS NOT NULL THEN results.Scenario3 ELSE 0 END) AS Scenario3,
(CASE WHEN results.Scenario4 IS NOT NULL THEN results.Scenario4 ELSE 0 END) AS Scenario4
FROM
(SELECT DISTINCT(suid), #suid:= suid,
(SELECT ur.data FROM tbluserresults ur WHERE ur.suid = #suid AND ur.sceneID = '1') AS Scenario1data,
(SELECT ss.score FROM tbluserscenescores ss WHERE ss.suid = #suid AND ss.sceneID = '1') AS Scenario1score,
(SELECT ur.data FROM tbluserresults ur WHERE ur.suid = #suid AND ur.sceneID = '2') AS Scenario2,
(SELECT ur.data FROM tbluserresults ur WHERE ur.suid = #suid AND ur.sceneID = '3') AS Scenario3,
(SELECT ur.data FROM tbluserresults ur WHERE ur.suid = #suid AND ur.sceneID = '4') AS Scenario4
FROM tbluserscenescores) AS results

Mysql query optimization takes more than 30 sec

Hi friends can any one please help me to optimize this query ,it takes more than 30 sec.
any suggestion is warmly welcome.
Query :
SELECT
CONCAT(CCD.CONTACT_FIRST_NAME, ' ', CCD.CONTACT_LAST_NAME) AS NAME,
A.EMAIL_IDS,
CCD.UNSUBSCRIBE,
IFNULL(CSL.LOG_DATE, '') AS LOG_DATE,
CSL.IP_ADDRESS,
IF(CSL.BROWSER IS NULL, '', CSL.BROWSER) AS BROWSER,
(CASE
WHEN (UNSUBSCRIBE = 0 OR UNSUBSCRIBE IS NULL) THEN 'Opted In'
ELSE (CASE
WHEN (UNSUBSCRIBE = 1) THEN 'Opted Out'
ELSE (CASE
WHEN
((UNSUBSCRIBE = 2 OR UNSUBSCRIBE = 3)
AND CCD.CONTACT_ID NOT IN (SELECT
CONTACT_ID
FROM
CM_SUBSCRIPTION_MAIL_DATA
WHERE
IS_MAIL_SENT = 'Y'))
THEN
'Opt-In Request not Sent'
ELSE 'Opt-In Pending'
END)
END)
END) AS CURR_SUB,
(CASE
WHEN (SUBSCRIBE_FROM = 0) THEN 'Opted In'
ELSE (CASE
WHEN (SUBSCRIBE_FROM = 1) THEN 'Opted Out'
ELSE (CASE
WHEN (SUBSCRIBE_FROM = 2 OR SUBSCRIBE_FROM = 3) THEN 'Opt-In Pending'
ELSE ''
END)
END)
END) AS SUB_FROM,
SUBSCRIBE_FROM,
(CASE
WHEN (SUBSCRIBE_TO = 0) THEN 'Opted In'
ELSE (CASE
WHEN (SUBSCRIBE_TO = 1) THEN 'Opted Out'
ELSE (CASE
WHEN (SUBSCRIBE_TO = 2 OR SUBSCRIBE_TO = 3) THEN 'Opt-In Pending'
ELSE ''
END)
END)
END) AS SUB_TO,
SUBSCRIBE_TO
FROM
CM_CONTACT_DETAILS CCD
LEFT JOIN
ADDRESS A ON CCD.CONTACT_ID = A.FOREIGN_ID
LEFT JOIN
CM_SUBSCRIPTION_LOGS CSL ON CSL.CONTACT_ID = CCD.CONTACT_ID
WHERE
1 = 1
GROUP BY CSL.LOG_DATE , CCD.CONTACT_ID
ORDER BY NAME DESC , LOG_DATE DESC
LIMIT 0 , 20
Your case/when can be simplified, but I believe the killer of your query was the correlated NOT IN SELECT clause for your Opt-in request not sent.
I've change your query to do a left-join to your mailing table based on the contact AND the mailed status of "Y". So this simplifies your case to only have to check for IS NULL of the mailing table contact ID.
You can't do too much on performance since your Group by is by columns from different tables that won't take advantage of any index optimization, then all that ordered by the name makes it more of an issue... but the correlated subquery per the field being executed every time to a left-join SHOULD help.
SELECT
CONCAT(CCD.CONTACT_FIRST_NAME, ' ', CCD.CONTACT_LAST_NAME) AS NAME,
A.EMAIL_IDS,
CCD.UNSUBSCRIBE,
IFNULL(CSL.LOG_DATE, '') AS LOG_DATE,
CSL.IP_ADDRESS,
IF(CSL.BROWSER IS NULL, '', CSL.BROWSER) AS BROWSER,
CASE WHEN UNSUBSCRIBE = 0 OR UNSUBSCRIBE IS NULL THEN 'Opted In'
WHEN UNSUBSCRIBE = 1 THEN 'Opted Out'
WHEN UNSUBSCRIBE IN (2,3) AND SMD.CONTACT_ID IS NULL THEN 'Opt-In Request not Sent'
ELSE 'Opt-In Pending' END AS CURR_SUB,
CASE WHEN SUBSCRIBE_FROM = 0 THEN 'Opted In'
WHEN SUBSCRIBE_FROM = 1 THEN 'Opted Out'
WHEN SUBSCRIBE_FROM = 2 OR SUBSCRIBE_FROM = 3 THEN 'Opt-In Pending'
ELSE '' END AS SUB_FROM,
SUBSCRIBE_FROM,
CASE WHEN SUBSCRIBE_TO = 0 THEN 'Opted In'
WHEN SUBSCRIBE_TO = 1 THEN 'Opted Out'
WHEN SUBSCRIBE_TO = 2 OR SUBSCRIBE_TO = 3 THEN 'Opt-In Pending'
ELSE '' END AS SUB_TO,
SUBSCRIBE_TO
FROM
CM_CONTACT_DETAILS CCD
LEFT JOIN ADDRESS A
ON CCD.CONTACT_ID = A.FOREIGN_ID
LEFT JOIN CM_SUBSCRIPTION_LOGS CSL
ON CSL.CONTACT_ID = CCD.CONTACT_ID
LEFT JOIN CM_SUBSCRIPTION_MAIL_DATA SMD
ON CCD.CONTACT_ID = SMD.CONTACT_ID
AND IS_MAIL_SENT = 'Y'
WHERE
1 = 1
GROUP BY
CSL.LOG_DATE,
CCD.CONTACT_ID
ORDER BY
NAME DESC,
LOG_DATE DESC
LIMIT
0, 20

Combine two MySQL queries to one

Is it possible to combine these two queries into one query?
SELECT sum(amount) as credit FROM statement WHERE userId= '33003' AND debitOrCredit = '1' AND actionDate <= '2012-10-17';
SELECT sum(amount) as debit FROM statement WHERE userId= '33003' AND debitOrCredit = '0' AND actionDate <= '2012-10-17';
so I get the result:
| credit | debit |
| 90 | 60 |
You could use CASE within your SUM:
SELECT sum(CASE WHEN debitOrCredit = '1' THEN amount ELSE 0 END) as credit,
sum(CASE WHEN debitOrCredit = '0' THEN amount ELSE 0 END) as debit
FROM statement WHERE userId= '33003' AND actionDate <= '2012-10-17';
use CASE in your SELECT clause
SELECT sum(CASE WHEN debitOrCredit = '1' THEN amount ELSE 0 END) as credit,
sum(CASE WHEN debitOrCredit = '0' THEN amount ELSE 0 END) as debit
FROM statement
WHERE userId= '33003' AND
actionDate <= '2012-10-17';
Use like this.
SELECT sum(a.amount) as credit,sum(b.amount) as debit FROM statement a left join statement b
on a.userId=b.userId
WHERE a.userId= '33003' AND a.debitOrCredit = '1' AND b.debitOrCredit = '0' AND a.actionDate <= '2012-10-17' AND b.actionDate <= '2012-10-17' ;
-- Mark answered if this answer answers your question...
Thank you for your help.
This is how I used it in Zend framework:
$sql = $this->_dba->select()
->from('statement', array(
"credit" => "sum(CASE WHEN debitOrCredit = '1' THEN amount ELSE 0 END)",
"debit" => "sum(CASE WHEN debitOrCredit = '0' THEN amount ELSE 0 END)"))
->where('userId = ?', $userId)
->where('actionDate <= ?', $date);
try
{
$result = $this->db->fetchRow($sql);
//process result here
}
catch (Exception $e)
{
throw new Exception("Error on ...... ");
}
Try this
SELECT sum(case when debitOrCredit = '1' then amount else 0 end) as credit, sum(case when debitOrCredit = '2' then amount else 0 end) as debit FROM statement WHERE userId= '33003' AND actionDate <= '2012-10-17'