Issue with Dynamic Pivot Table - php

Having some issues with my query in that it generates the required data between the dates specified (on live it is 2 date fields (date_from and date_to), but the order of data is in the wrong order. e.g it will appear
JAN 2017 | MARCH 2017 | APRIL 2017 | FEB 2017
And the most baffling issue is that it generates data outside what you search. e.g if you search from 1-1-2017 to date, it adds December to the data but there is no data in the database containing december records.
The code used to generate the dynamic pivot chart is:
$sql = "
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN EXTRACT(".$period." FROM redeem_pledge) = ',
EXTRACT(".$period." FROM redeem_pledge),
' THEN AMOUNT else 0 END) AS `',
EXTRACT(".$period." FROM redeem_pledge),
'`'
)
) AS `pivot_columns`
FROM record_pledge
WHERE redeem_pledge BETWEEN ? AND ?
ORDER BY redeem_pledge asc
";
$stmt = $pdo->prepare($sql);
$date_from = $this->input->get('date_from') ? $this->input->get('date_from') : '2017-05-01';
$date_to = $this->input->get('date_to') ? $this->input->get('date_to') : date('Y-m-d');
$stmt->execute([$date_from, $date_to]);
$row = $stmt->fetch();
$stmt->closeCursor();
$pivot_columns = $row['pivot_columns'];
$sql = "
SELECT title AS `Pledge Purpose`, {$pivot_columns}
FROM record_pledge t1
JOIN setting_pledge_purpose ON t1.purpose_pledge = setting_pledge_purpose.id
WHERE t1.redeem_pledge BETWEEN ? AND ?
GROUP BY title asc WITH ROLLUP
";
$stmt = $pdo->prepare($sql);
$stmt->execute([$date_from, $date_to]);
$results = $stmt->fetchAll();
$stmt->closeCursor();
Image of Added data and unorganised data:
UPDATE echo of SQL- SEARCH FROM 01-01-2017(JAN) - 15-10-2017(OCT) :
SELECT title AS `Pledge Purpose`,
SUM(CASE WHEN EXTRACT(YEAR_MONTH FROM redeem_pledge) = 201701 THEN AMOUNT else 0 END) AS `201701`,
SUM(CASE WHEN EXTRACT(YEAR_MONTH FROM redeem_pledge) = 201702 THEN AMOUNT else 0 END) AS `201702`,
SUM(CASE WHEN EXTRACT(YEAR_MONTH FROM redeem_pledge) = 201704 THEN AMOUNT else 0 END) AS `201704`,
SUM(CASE WHEN EXTRACT(YEAR_MONTH FROM redeem_pledge) = 201705 THEN AMOUNT else 0 END) AS `201705`,
SUM(CASE WHEN EXTRACT(YEAR_MONTH FROM redeem_pledge) = 201706 THEN AMOUNT else 0 END) AS `201706`,
SUM(CASE WHEN EXTRACT(YEAR_MONTH FROM redeem_pledge) = 201708 THEN AMOUNT else 0 END) AS `201708`,
SUM(CASE WHEN EXTRACT(YEAR_MONTH FROM redeem_pledge) = 201709 THEN AMOUNT else 0 END) AS `201709`
FROM record_pledge t1 JOIN setting_pledge_purpose ON t1.purpose_pledge = setting_pledge_purpose.id
WHERE t1.redeem_pledge BETWEEN ? AND ? GROUP BY title asc WITH ROLLUP

You need to put the ORDER BY option in the GROUP_CONCAT function, not the SELECT query.
Also, you need to put quotes around the value returned by EXTRACT($period FROM redeem_pledge). If $period is a unit that returns multiple parts of the date, like YEAR_MONTH, it needs to be compared as a string because it will be 2017-01; if you don't quote it, it will be treated as a numeric subtraction.
$sql = "
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN EXTRACT(".$period." FROM redeem_pledge) = \"',
EXTRACT(".$period." FROM redeem_pledge),
'\" THEN AMOUNT else 0 END) AS `',
EXTRACT(".$period." FROM redeem_pledge),
'`'
)
ORDER BY redeem_pledge ASC) AS `pivot_columns`
FROM record_pledge
WHERE redeem_pledge BETWEEN ? AND ?
";

Related

Codeigniter-Problem in Where while using group by week starting from tuesday

I have to use yearweek() in my CodeIgniter query to group the data by week starting from Tuesday.that was working fine without a problem. then the main problem is to filter was doesn't work with Tuesday dates.that was filtered only yearweek() in where on Sunday dates.
I tried that by writing a raw query that was working fine. then I was analyzing on my query then I have found the problem. that was doesn't show equal(=) symbol between where column and values.i was put my CodeIgniter code and correct raw query then current CodeIgniter equivalent query below
function getbranchSalesreportshift($limit,$offset,$order_column,$order_type,$parameters)
{
$this->db->select("str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') as week,b.name as branchname,g.name as groupname,st.name as shiftname,count(*) as total_sales_party,sum(s.price) as total_sales,count(case when salesAdvanceAmount > 0 then s.customerid end) as total_advance_party,sum(case when salesAdvanceAmount > 0 then salesAdvanceAmount end) as total_advance_amount,count(CASE WHEN DATE(s.creationdate) <> Date(customerCreationDate) then 1 end ) as old_sales_party,sum(CASE WHEN DATE(s.creationdate) <> Date(customerCreationDate) THEN s.price END ) as old_sales_amount,count(CASE WHEN DATE(s.creationdate) = Date(customerCreationDate) THEN 1 END ) as new_sales_party,sum(CASE WHEN DATE(s.creationdate) = Date(customerCreationDate) THEN s.price END ) as new_sales_amount,count(returnID) as return_product,sum(orn.price) as return_amount ");
if($parameters['shift']!=NULL){
$this->db->like('s.shiftID',$parameters['shift']);
}
if($parameters['cdatefrom']!=NULL){
// $this->db->where('yearweek(s.creationdate)',date('YW',strtotime($parameters['cdatefrom'])));
$this->db->where('str_to_date(concat(yearweek(s.creationdate), "tuesday"), "%X%V %W")',date('YW',strtotime($parameters['cdatefrom'])));
}
$this->db->group_by(array("s.shiftID", "str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W')"));
if(empty($order_column) || empty($order_type)){
$this->db->order_by('yearweek(s.creationdate)','asc');
}else{
$this->db->order_by($order_column,$order_type);
}
if($limit!=0){
$this->db->limit($limit,$offset);
}
$uid=$this->session->userdata('id');
$this->db->where('b.ownerid',$uid);
$this->db->join('open_returns orn','s.branchID=orn.branchID ','left');
$this->db->join('shifts st','s.shiftID=st.id ','left');
$this->db->join('group g','s.groupID=g.id ','left');
$this->db->join('branch b','s.branchID=b.id ','left');
$query = $this->db->get('super_sales s');
if($query->num_rows()>0){
return $query->result_array();
}else{
return FALSE;
}
}
this is my equivelent raw query (equal symbol cann't put between column and value near where)
SELECT str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') as week, `b`.`name` as `branchname`, `g`.`name` as `groupname`, `st`.`name` as `shiftname`, count(*) as total_sales_party, sum(s.price) as total_sales, count(case when salesAdvanceAmount > 0 then s.customerid end) as total_advance_party, sum(case when salesAdvanceAmount > 0 then salesAdvanceAmount end) as total_advance_amount, count(CASE WHEN DATE(s.creationdate) <> Date(customerCreationDate) then 1 end ) as old_sales_party, sum(CASE WHEN DATE(s.creationdate) <> Date(customerCreationDate) THEN s.price END ) as old_sales_amount, count(CASE WHEN DATE(s.creationdate) = Date(customerCreationDate) THEN 1 END ) as new_sales_party, sum(CASE WHEN DATE(s.creationdate) = Date(customerCreationDate) THEN s.price END ) as new_sales_amount, count(returnID) as return_product, sum(orn.price) as return_amount FROM `super_sales` `s` LEFT JOIN `open_returns` `orn` ON `s`.`branchID`=`orn`.`branchID` LEFT JOIN `shifts` `st` ON `s`.`shiftID`=`st`.`id` LEFT JOIN `group` `g` ON `s`.`groupID`=`g`.`id` LEFT JOIN `branch` `b` ON `s`.`branchID`=`b`.`id` WHERE str_to_time(concat(yearweek(s.creationdate), "tuesday"), "%X%V %W") '201842' AND `b`.`ownerid` = '189' GROUP BY `s`.`shiftID`, str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') ORDER BY `week` DESC LIMIT 50
I was found correct raw query as below but I need correct CodeIgniter coding for respective filter/where
SELECT str_to_date(concat(yearweek(creationdate), 'sunday'), '%X%V %W') as week,b.name as branchname,g.name as groupname,st.name,count(*) as total_sales_party,sum(price) as total_sales,count(case when salesAdvanceAmount > 0 then customerid end) as total_advance_party,sum(case when salesAdvanceAmount > 0 then salesAdvanceAmount end) as total_advance_amount,count(CASE WHEN DATE(creationdate) <> Date(customerCreationDate) then 1 end ) as old_sales_party,sum(CASE WHEN DATE(creationdate) <> Date(customerCreationDate) THEN price END ) as old_sales_amount,count(CASE WHEN DATE(creationdate) = Date(customerCreationDate) THEN 1 END ) as new_sales_party,sum(CASE WHEN DATE(creationdate) = Date(customerCreationDate) THEN price END ) as new_sales_amount FROM `super_sales` `s` LEFT JOIN branch b ON `s`.branchID=b.id LEFT JOIN `group` g ON `s`.groupID=g.id LEFT JOIN shifts st ON s.shiftID=st.id where str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W') = '2018-10-16' AND b.ownerid=189 GROUP BY str_to_date(concat(yearweek(s.creationdate), 'tuesday'), '%X%V %W'),s.shiftID ORDER BY week DESC
I need to filter the data by Tuesday weekdays like week column in select
this is a pretty tough one - because, you've to know how the query builder and the underlying DB Driver are working.
The problem is, usually the Querybuilder suffixes in case of a where condition the given key with an = per default. However in your case it doesn't because it thinks it has an operator.
This exactly happens in the following lines:
https://github.com/bcit-ci/CodeIgniter/blob/develop/system/database/DB_query_builder.php#L681
and
https://github.com/bcit-ci/CodeIgniter/blob/develop/system/database/DB_driver.php#L1485
you may found a bug here - and the best thing is to report it on the Forum.
Your solution for now is to suffix it by your own:
$this->db->where('str_to_date(concat(yearweek(s.creationdate), "tuesday"), "%X%V %W") =',date('YW',strtotime($parameters['cdatefrom'])));

How to convert this complex query into active record CODEIGNITER PHP?

I have these queries in my ORACLE SQL:
SELECT dep.airport AS DEPAIRPORT,
dep.scheduled AS SCHEDULED,
dep.ontime AS ONTIME,
arr.arrontime AS ARRONTIME FROM (SELECT AIRPORT,sum(FIRSTFLIGHT) AS FIRSTFLIGHT, SUM(OTPFIRSTFLIGHT) as OTPFIRSTFLIGHT, SUM(ZMDFIRSTFLIGHT) as ZMDFIRSTFLIGHT,
COUNT(SCHEDULED) AS SCHEDULED,COUNT(ONTIME) AS ONTIME, COUNT(SCHEDARR) AS SCHEDARR FROM (SELECT DEPAIRPORT as AIRPORT,
MAX(case when A.STATUS = 'Scheduled' and
A.ACTUAL_BLOCKOFF is not null then 1 else NULL END) as SCHEDULED,
MAX(case when ((A.ACTUAL_BLOCKOFF+ interval '7' hour) - (A.SCHEDULED_DEPDT+ interval '7' hour))*24*60 <= '+000000015 00:00:00.000000000' and
A.ACTUAL_BLOCKOFF is not null then 1 else NULL END) as ONTIME,
MAX(case when A.STATUS = 'Scheduled' and A.ACTUAL_BLOCKON is not null then 1 else NULL END) as SCHEDARR
FROM TABLEA A left join TABLEB B ON A.FLIGHTLEGREF = B.FLIGHTLEGREF
where A.SERVICETYPE IN ('J','G') and to_char(SCHEDULED_DEPDT + interval '7' hour, 'yyyy-mm-dd') between '2018-07-15' and '2018-07-21'
and A.LATEST_ARRIVALAIRPORT != A.SCHED_DEPARTUREAIRPORT and (SUFFIX != 'R' or SUFFIX IS NULL)
group by DEPAIRPORT, AIRCRAFTREG,SCHEDULED_DEPDT,ACTUAL_BLOCKOFF,ACTUAL_BLOCKON,AIRCRAFTTYPE,SCHEDULED_ARRDT)GROUP BY AIRPORT) dep
left join (SELECT sched_arrivalairport AS airport,
count(CASE
WHEN( ( a.actual_blockon + interval '7' hour ) - (
a.scheduled_arrdt + interval '7' hour ) ) *
24 *
60
<=
'+000000015 00:00:00.000000000'
AND a.actual_blockon IS NOT NULL THEN 1
END) AS arrontime
FROM TABLEA A
where A.SERVICETYPE IN ('J','G') and to_char(SCHEDULED_DEPDT + interval '7' hour, 'yyyy-mm-dd') between '2018-07-15' and '2018-07-21'
and A.LATEST_ARRIVALAIRPORT != A.SCHED_DEPARTUREAIRPORT and (SUFFIX != 'R' or SUFFIX IS NULL)
GROUP BY sched_arrivalairport)arr
ON ( dep.airport = arr.airport )order by dep.airport `
and those codes works perfectly when I compiled it in oracle sql developer.
but when I converted to active record in code igniter the code didnt works.
here is my converted code in php:
$CI->db->select("DEP.AIRPORT AS DEPAIRPORT,
DEP.scheduled AS SCHEDULED,
DEP.ontime AS ONTIME,
ARR.arrontime AS ARRONTIME");
$CI->db->from("(");
$subq3 = $CI->db->get_compiled_select();
//$CI->db->reset_query();
$CI->db->select("DEPAIRPORT,sum(FIRSTFLIGHT) AS FIRSTFLIGHT, SUM(OTPFIRSTFLIGHT) as OTPFIRSTFLIGHT, SUM(ZMDFIRSTFLIGHT) as ZMDFIRSTFLIGHT,"
. "SUM(SCHEDULED) AS SCHEDULED,SUM(ONTIME) AS ONTIME");
$CI->db->from("(SELECT DEPAIRPORT as DEPAIRPORT,
MAX(case when A.STATUS = 'Scheduled' and
A.ACTUAL_BLOCKOFF is not null then 1 else NULL END) as SCHEDULED,
MAX(case when ((A.ACTUAL_BLOCKOFF+ interval '7' hour) - (A.SCHEDULED_DEPDT+ interval '7' hour))*24*60 <= '+000000015 00:00:00.000000000' and
A.ACTUAL_BLOCKOFF is not null then 1 else NULL END) as ONTIME FROM TABLEA A");$CI->db->join('TABLEB B', 'A.FLIGHTLEGREF = B.FLIGHTLEGREF','left');
$CI->db->where("A.LATEST_ARRIVALAIRPORT != A.SCHED_DEPARTUREAIRPORT"); $CI->db->where(divertStatus());
if ($stnService == "dom"){
$CI->db->where("A.SCHED_DEPARTUREAIRPORT IN (".$domstn.")");
}
if ($stnService == "int"){
$CI->db->where("A.SCHED_DEPARTUREAIRPORT IN (".$intstn.")");
}
if ($aptMgmt == "ap1"){
$CI->db->where_in("A.SCHED_DEPARTUREAIRPORT",$AP1);
}
if ($aptMgmt == "ap2"){
$CI->db->where_in("A.SCHED_DEPARTUREAIRPORT",$AP2);
}
if(!is_null($date1) && !is_null($date2))
$CI->db->where("to_char(SCHEDULED_DEPDT + interval '7' hour, 'yyyy-mm-dd') between '".$date1."' and '".$date2."'");
else $CI->db->where($timeLimit);
$CI->db->where("A.SERVICETYPE IN ('J','G')");
$CI->db->group_by("DEPAIRPORT, AIRCRAFTREG,SCHEDULED_DEPDT,ACTUAL_BLOCKOFF,ACTUAL_BLOCKON,AIRCRAFTTYPE,SCHEDULED_ARRDT) GROUP BY DEPAIRPORT) DEP ");
$subq1 = $CI->db->get_compiled_select();
//$CI->db->reset_query();
$CI->db->select("SCHED_ARRIVALAIRPORT AS AIRPORT,
count(CASE
WHEN( ( A.ACTUAL_BLOCKON + interval '7' hour ) - (
A.SCHEDULED_ARRDT + interval '7' hour ) ) *
24 *
60
<=
'+000000015 00:00:00.000000000'
AND A.ACTUAL_BLOCKON IS NOT NULL THEN 1
END) AS arrontime ");
$CI->db->from("TABLEA A ");
if(!is_null($date1) && !is_null($date2))
$CI->db->where("to_char(SCHEDULED_DEPDT + interval '7' hour, 'yyyy-mm-dd') between '".$date1."' and '".$date2."'");
else $CI->db->where($timeLimit);
$CI->db->where("A.SERVICETYPE IN ('J','G')");
$CI->db->where("A.LATEST_ARRIVALAIRPORT != A.SCHED_DEPARTUREAIRPORT"); $CI->db->where(divertStatus());
$CI->db->group_by("SCHED_ARRIVALAIRPORT)arr ON DEP.AIRPORT = ARR.AIRPORT");
$CI->db->order_by("DEP.DEPAIRPORT ASC");
$subq2 = $CI->db->get_compiled_select();
//$CI->db->reset_query();
$CI->db->query("$subq3 $subq1 LEFT JOIN ($subq2");
when I tried to compile the converted code it always produces result like this
Error Number: 904
ORA-00904: "DEP"."AIRPORT": invalid identifier
Did I miss something in my converted code ?
Any suggestion would be appreciated. Thankss
You can try to use Codeigniter query() function. Try this:
$your_query = "paste here your ORACLE SQL";
$result = $CI->db->query($your_query)->result_array();
This function return array of results. Docs here https://www.codeigniter.com/userguide3...

Dynamic Pivot MYSQL incomplete SQL

I have been having trouble with a project i've been working on for about 5 weeks now, i've made various stackoverflow posts along the way and i'm almost at the final hurdle.
I was having issues with duplicated data searching weekly sums but I seem to have figured that out but now my statement isn't completing.
REf:
Weekly Sum Dynamic Pivot MYSQL
Here is a fiddle with the data.
http://sqlfiddle.com/#!9/a3610
$period = 'YEARWEEK';
$sql = "
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'SUM(CASE WHEN (".$period."(date)) = ',
(".$period."(date)),
' THEN AMOUNT else 0 END) AS `',
(".$period."(date)),
'`'
)
ORDER BY date ASC ) AS `pivot_columns`
FROM record_offering
WHERE date BETWEEN ? AND ?
ORDER BY date ASC
";
$stmt = $pdo->prepare($sql);
$date_from = '2017-01-01';
$date_to = '2017-10-01';
$stmt->execute([$date_from, $date_to]);
$row = $stmt->fetch();
$stmt->closeCursor();
$pivot_columns = $row['pivot_columns'];
$sql = "
SELECT title AS `Service`, {$pivot_columns}
from record_offering t1
join setting_service ON t1.service_id = setting_service.id
WHERE t1.date BETWEEN ? AND ?
GROUP BY title asc WITH ROLLUP
";
$stmt = $pdo->prepare($sql);
$stmt->execute([$date_from, $date_to]);
$results = $stmt->fetchAll();
$stmt->closeCursor();
As you can see the last statement is incomplete:
SELECT title AS `Service`, SUM(CASE WHEN (YEARWEEK(date)) = 201635 THEN AMOUNT else 0 END) AS `201635`,
SUM(CASE WHEN (YEARWEEK(date)) = 201703 THEN AMOUNT else 0 END) AS `201703`,
SUM(CASE WHEN (YEARWEEK(date)) = 201709 THEN AMOUNT else 0 END) AS `201709`,
SUM(CASE WHEN (YEARWEEK(date)) = 201713 THEN AMOUNT else 0 END) AS `201713`,
SUM(CASE WHEN (YEARWEEK(date)) = 201715 THEN AMOUNT else 0 END) AS `201715`,
SUM(CASE WHEN (YEARWEEK(date)) = 201717 THEN AMOUNT else 0 END) AS `201717`,
SUM(CASE WHEN (YEARWEEK(date)) = 201718 THEN AMOUNT else 0 END) AS `201718`,
SUM(CASE WHEN (YEARWEEK(date)) = 201722 THEN AMOUNT else 0 END) AS `201722`,
SUM(CASE WHEN (YEARWEEK(date)) = 201723 THEN AMOUNT else 0 END) AS `201723`,
SUM(CASE WHEN (YEARWEEK(date)) = 201725 THEN AMOUNT else 0 END) AS `201725`,
SUM(CASE WHEN (YEARWEEK(date)) = 201726 THEN AMOUNT else 0 END) AS `201726`,
SUM(CASE WHEN (YEARWEEK(date)) = 201735 THEN AMOUNT else 0 END) AS `201735`,
SUM(CASE WHEN (YEARWEEK(date)) = 201736 THEN AMOUNT else 0 END) AS `201736`,
SUM(CASE WHEN (YEARWEEK(date)) = 201
from record_offering t1
join setting_service ON t1.service_id = setting_service.id
WHERE t1.`date` BETWEEN ? AND ?
GROUP BY title asc WITH ROLLUP
I have tried escaping the query in various ways but either the query completes and my data is duplicated or it doesn't compile at all.
GROUP_CONCAT has a limit off 1024 bytes.
Use
SET SESSION group_concat_max_len = ##max_allowed_packet
Before the GROUP_CONCAT query.
To my way of thinking, this (or something very like it) is ALL the sql you need for this problem. Everything else can, and should, be handled in the presentation layer.
SELECT YEARWEEK(x.date) yw
, x.title
, COALESCE(SUM(y.amount),0) total
FROM setting_service x
LEFT
JOIN record_offering y
ON y.service_id = x.id
GROUP
BY yw
, x.id;

Closing percent MATH in MYSQL

I want to do math in a query, and was wondering if its better to do it in PHP or MYSQL.
Also, if I choose MYSQL can anyone help me with the query.
So far I have
SELECT COUNT(*) as total, booker, appdate,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) book,
SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) tot
FROM appts WHERE WEEK(app_date)= WEEK(CURDATE()) GROUP BY booker
I want one more stat from this query.
I want to do book / (book+tot)
But obviously only if book!=0 or tot!=0, since obviously I don't want to divide anything by zero.
Is there a way to do this in a MYSQL query??
I want my output to be.....
book | 14
tot | 25
hold | 35%
Id also like to ORDER BY the hold percent from highest to lowest. Is this possible????
You can achieve what you ask for using a subquery, like this:
SELECT *, IF(book + tot, 100*book/(book + tot), NULL) AS hold
FROM (
SELECT COUNT(*) as total, booker, appdate,
SUM(status='DNS') book, SUM(status!='DNS') tot
FROM appts WHERE WEEK(app_date)= WEEK(CURDATE()) GROUP BY booker
) AS subquery
ORDER BY hold DESC
Note that in several places I'm using the fact that MySQL uses numbers for logical values. So you can sum up conditions without CASE, and you can write a formula for IF without <> 0 check.
Naive method:
SELECT
COUNT(*) as total,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) book,
SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) tot,
IF( ( SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) +
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) ) = 0,
0,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) /
( SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) +
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) )
) AS hold
FROM appts
WHERE WEEK(app_date) = WEEK(CURDATE()) GROUP BY booker
ORDER BY hold;
Or in order not to repeat your aliases, use a subquery:
SELECT *, IF (book + tot = 0, 0, book / (book + tot) * 100)
FROM (
SELECT
COUNT(*) as total,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) book,
SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) tot,
FROM appts
WHERE WEEK(app_date) = WEEK(CURDATE()) GROUP BY booker
) AS subq
ORDER BY hold;
Or, more cleverly :) (book + tot = total)
SELECT *, IF (total = 0, 0, book / total * 100)
FROM (
SELECT
COUNT(*) as total,
SUM(CASE WHEN status='DNS' THEN 1 ELSE 0 END) book,
SUM(CASE WHEN status!='DNS' THEN 1 ELSE 0 END) tot,
FROM appts
WHERE WEEK(app_date) = WEEK(CURDATE()) GROUP BY booker
) AS subq
ORDER BY hold;
And, just for fun, the hackishly compactest form:
SELECT *, COALESCE(book / total * 100, 0) AS hold -- a division by 0 returns NULL
FROM (
SELECT
COUNT(*) total,
SUM(status='DNS') book, -- boolean "true" is internally integer "1"
SUM(status!='DNS') tot,
FROM appts
WHERE WEEK(app_date) = WEEK(CURDATE()) GROUP BY booker
) AS subq
ORDER BY hold;

select/sum of a column with different conditions in 1 query

$pos = select * from score_history where content_id = 6 && val = 1
$neg = select * from score_history where content_id = 6 && val = -1
i want to get the pos and neg scores in one query
but i dont want to use join
so perhaps some sort of IF/case statement ?
i've this but as you can guess it fails
SELECT count(*) as total ,
CASE
WHEN `val` = 1 THEN count(*) as `pos`
WHEN `val` = -1 THEN count(*) as `neg`
END
FROM score_history WHERE `content_id` = '46083' ";
is there any way to do this without using join or sub query ?
You can make use of the flexibility of MySQL to handle booleans and integers:
SELECT count(*) total, sum(val = 1) pos, sum(val = -1) neg
FROM score_history
WHERE content_id = '46083';
Whenever the condition is true it is a 1. Otherwise a 0. No CASE needed nor GROUP BY.
Close! A CASE statement doesn't return multiple columns, so you'll need 2 CASE statements and to wrap them in a SUM():
SELECT count(*) as total
,SUM(CASE WHEN `val` = 1 THEN 1 ELSE 0 END) as `pos`
,SUM(CASE WHEN `val` = -1 THEN 1 ELSE 0 END) as `neg`
FROM score_history WHERE `content_id` = '46083' ;
SELECT
SUM(CASE WHEN `val` = 1 THEN 1 ELSE O END) AS pos_count,
SUM(CASE WHEN `val` = -1 THEN 1 ELSE O END) AS neg_count
FROM score_history WHERE `content_id` = '46083';
Try this. Sorry I can't test, no database on this laptop.
select
count(*) as total,
sum(case val when 1 then 1 else 0 end) as pos,
sum(case val when -1 then 1 else 0 end) as neg
from score_history
where content_id = 6
Not sure if this is the best answer (and you would certainly want an index on your val column assuming there are many rows in the table) but this should certainly work - also assuming you only have 1 and -1 as values:
SELECT count(*), val from score_history where content_id = 6 group by val;
You were close; try the SUM function:
SELECT count(*) as total
, sum(CASE WHEN `val` = 1 THEN 1 ELSE 0 END) as `pos`
, sum(CASE WHEN `val` = -1 THEN 1 ELSE 0 END) as `neg`
FROM score_history
WHERE `content_id` = '46083';
select count(*)
from score_history
where content_id = 6 &&
(val = -1 or val=1)
group by val
I think this statement should work but I have tested on DBMS.
SELECT count(*) as total ,
count(case when val = 1 then 1 else null end) as pos,
count(case when val = -1 then 1 else null end) as neg
FROM score_history
WHERE `content_id` = '46083';
See SQLFIDDLE
Okay, a lot of these answers are close, but whenever you use an aggregate function you should use a group by.
SELECT count(*) as total
, (CASE WHEN `val` >= 0 THEN 'positive' ELSE 'negative' END) as interpreted_value
END
FROM score_history
WHERE `content_id` = '46083'
GROUP BY (CASE WHEN `val` >= 0 THEN 'positive' ELSE 'negative' END);
If you want to read up on how to use group by and aggregate functions here: https://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html

Categories