Mysql: How to query with if else condition inside if - mysql

I'm getting trouble to query my data. I do not know where to start with query if else condition inside if.
Problem is:
How to query if its type = cpm and end_date < now() then change result value type to before, and if its type = cpm and end_date > now() then change result value type to after.
I have a data in table, result as below :
And I want to get
result as below :
Array(
[0] => Array
(
[id] => 1
[type] => free
[end_date] => 2013-06-20
)
[1] => Array
(
[id] => 4
[type] => after
[end_date] => 2013-08-29
)
[2] => Array
(
[id] => 5
[type] => before
[end_date] => 2013-06-20
)
)
Thanks in advance.

Something like this should work:
select
id,
case
when (type = 'cpm' and end_date < now()) then 'before'
when (type = 'cpm' and end_date > now()) then 'after'
else type
end as type,
end_date
from my_table;

You could use MySQL CASE - http://dev.mysql.com/doc/refman/5.0/en/control-flow-functions.html#operator_case
CASE
WHEN `type` = 'cpm' AND `end_date` < NOW() THEN 'before'
WHEN `type` = 'cpm' AND `end_date` > NOW() THEN 'after'
ELSE `type`
END as `type`

You can use WHEN .. CASE for this .
Here is Link for your solution SQLfiddle

Related

Get month wise count from Mysql database even if there are no results

I am creating graph for display month wise count from Mysql database.
Execute this following query:
$cash_query = $this->db->query("select COUNT(*) as count_monthwise, MONTH(FROM_UNIXTIME(dt_added)) as month from `order` where user_id='1' and status != '9' and payment_type = '1' GROUP BY month");
$cash_result = $cash_query->result();
Output:
Array
(
[0] => stdClass Object
(
[count_monthwise] => 1
[month] => 8
)
[1] => stdClass Object
(
[count_monthwise] => 2
[month] => 9
)
)
In above output, there are display "count_monthwise" means count and month "8" means "8th month - August".
But i want to display output with all months, if find count are 0 in any months, then display [count_monthwise] => 0.
I want to display Exact output like:
Array
(
[0] => stdClass Object
(
[count_monthwise] => 1
[month] => 1
)
[1] => stdClass Object
(
[count_monthwise] => 1
[month] => 2
)
.
.
.
.
.
.
.
[10] => stdClass Object
(
[count_monthwise] => 0
[month] => 11
)
[11] => stdClass Object
(
[count_monthwise] => 0
[month] => 12
)
)
I have used using foreach loop something like this, but this is not working.
Loop
foreach($cash_result as $cash => $cash_value){
for($i=0;$i<=11;$i++){
if($i == $cash){
}
}
}
That could be the one way around:
SELECT
COALESCE(yourQuery.count_monthwise,0) AS monthwise_count,
allMonths.month
(SELECT 1 AS month UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12 ) AS allMonths
LEFT JOIN
(
SELECT
COUNT(*) as count_monthwise,
MONTH(FROM_UNIXTIME(dt_added)) as month
from `order`
where user_id='1' and status != '9' and payment_type = '1'
GROUP BY month
) AS yourQuery
ON allMonths.month = yourQuery.month
use below way after getting the result from database don't do complex query just do some code twist
$cash_result = $cash_query->result_array(); // make it to array
$month = range(1,12); // month array
$new_array = array();
$counta = count($month);
for($i=0; $i<$counta ; $i++){
foreach($arr as $key=>$row){
if(($month[$i] == $row['month'])){
$new_array[$i] = $arr[$key];
break;
}else{
$new_array[$i] = array('count_monthwise' => 0,'month' => $month[$i]);
}
}
}
echo '<pre>'; print_r($new_array);

sum doesn't work while I use left join and group by

I have two table: imports and orders: I have attached these respectively.
I want the followings:
1. sum amount of same product_id in imports table
2. sum of pieces of same product_id in orders table as status wise.
my query is:
SELECT `Import`.*,
SUM( case when orders.status = "sold" THEN orders.pieces else 0 end) as total_sell,
SUM( case when orders.status = "No contact" THEN orders.pieces else 0 end) as no_contact,
SUM( case when orders.status = "confirmed" THEN orders.pieces else 0 end) as confirmed,
SUM( case when orders.status = "canceled" THEN orders.pieces else 0 end) as canceled
FROM `amrajegeachi`.`imports` AS `Import`
LEFT JOIN `orders`
ON `Import`.`product_id` = `orders`.`product_id`
WHERE 1 = 1
GROUP BY `Import`.`id`
and result for this query:
Array
(
[0] => Array
(
[Import] => Array
(
[id] => 1
[category_id] => 2
[product_id] => 2
[amount] => 50
[cost] => 8320
[comment] => transportation and others cost: 100
[created] => 2015-06-23 19:21:10
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 1
[confirmed] => 2
[canceled] => 0
)
)
[1] => Array
(
[Import] => Array
(
[id] => 2
[category_id] => 2
[product_id] => 2
[amount] => 15
[cost] => 3000
[comment] =>
[created] => 2015-06-22 18:10:36
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 1
[confirmed] => 2
[canceled] => 0
)
)
[2] => Array
(
[Import] => Array
(
[id] => 3
[category_id] => 2
[product_id] => 1
[amount] => 15
[cost] => 2000
[comment] =>
[created] => 2015-06-23 19:20:15
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 0
[confirmed] => 0
[canceled] => 0
)
)
)
My expected result is:
Array
(
[0] => Array
(
[Import] => Array
(
[id] => 1
[category_id] => 2
[product_id] => 2
[amount] => 65
[cost] => 8320
[comment] => transportation and others cost: 100
[created] => 2015-06-23 19:21:10
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 1
[confirmed] => 2
[canceled] => 0
)
)
[2] => Array
(
[Import] => Array
(
[id] => 3
[category_id] => 2
[product_id] => 1
[amount] => 15
[cost] => 2000
[comment] =>
[created] => 2015-06-23 19:20:15
)
[0] => Array
(
[total_sell] => 10
[no_contact] => 0
[confirmed] => 0
[canceled] => 0
)
)
)
How can I do this? I tried in different way such as:
SELECT `Import`.*, SUM(`Import`.`amount`) as total_import,
SUM( case when orders.status = "sold" THEN orders.pieces else 0 end) as total_sell,
SUM( case when orders.status = "No contact" THEN orders.pieces else 0 end) as no_contact,
SUM( case when orders.status = "confirmed" THEN orders.pieces else 0 end) as confirmed,
SUM( case when orders.status = "canceled" THEN orders.pieces else 0 end) as canceled
FROM `amrajegeachi`.`imports` AS `Import`
LEFT JOIN `orders`
ON `Import`.`product_id` = `orders`.`product_id`
WHERE 1 = 1
GROUP BY `Import`.`id`
But no luck :'(
I am guessing that you want information about each product. If so, you can do this in a few ways. Here is a union all method:
SELECT product_id, sum(amount) as total_import,
sum( case when status = 'sold' THEN pieces else 0 end) as total_sell,
sum( case when status = 'No contact' THEN pieces else 0 end) as no_contact,
sum( case when status = 'confirmed' THEN pieces else 0 end) as confirmed,
sum( case when status = 'canceled' THEN pieces else 0 end) as canceled
from ((select i.product_id, amount, NULL as status, NULL as pieces
from `amrajegeachi`.`imports` i
) union all
(select o.product_id, NULL, o.status, o.pieces
from `orders` o
)
) io
group by product_id;
SELECT `Import`.*, SUM(`Import`.`amount`) as total_import,
SUM( case when orders.status = "sold" THEN orders.pieces else 0 end) as total_sell,
SUM( case when orders.status = "No contact" THEN orders.pieces else 0 end) as no_contact,
SUM( case when orders.status = "confirmed" THEN orders.pieces else 0 end) as confirmed,
SUM( case when orders.status = "canceled" THEN orders.pieces else 0 end) as canceled
FROM `amrajegeachi`.`imports` AS `Import`
LEFT JOIN `orders`
ON `Import`.`product_id` = `orders`.`product_id`
WHERE 1 = 1
GROUP BY `Import`.`id

SQL, MySQL and php

I have 2 tables
CREATE TABLE `employee` (
`Employee_ID` smallint(4) NOT NULL AUTO_INCREMENT,
`Name` varchar(25) NOT NULL DEFAULT '',
PRIMARY KEY (`Employee_ID`)
) ;
--- -----------------
CREATE TABLE `attendance` (
`Attendance_ID` int(9) NOT NULL AUTO_INCREMENT,
`Employee_ID` smallint(3) NOT NULL,
`Date` date NOT NULL,
`Attendance` char(1) NOT NULL DEFAULT '',
PRIMARY KEY (`Attendance_ID`)
) ;
For Attendance field it's a "P" when the employee is present "L" when late and "A" when absent.
I want to make a query that crosses the dates with employees names and show atendance.
Something similar to:
Attendance 07/02/2015 14/02/2015 21/02/2015 ...
Diane P P L
Robert A P P
Karine P P A
...
I didn't post any query because actually I failed many times to figure out how to
Thanks for help
I do not know how to get dynamic columns in MySQL. This is how I would do it:
SELECT attd.Date, attd.Attendance, empl.Name FROM attendance attd, employee empl WHERE empl.Employee_ID = attd.Employee_ID
That will give result:
Then I would use server side code (example PHP):
<?php
$attendance = array();
foreach ($query as $row) {
if (isset($attendance[$row['Name']])) {
$attendance[$row['Name']][$row['Date']] = $row['Attendance'];
} else {
$attendance[$row['Name']] = array($row['Date'] => $row['Attendance']);
}
}
print_r($attendance);
/* Array(
"Diane" => Array("2015-02-07" => 'P', "2015-02-14" => 'P'),
"Robert" => Array("2015-02-07" => 'P', "2015-02-14" => 'P'),
"Karine" => Array("2015-02-07" => 'L', "2015-02-14" => 'L')
)
*/
select
a.Employee_ID,
min(e.Name) as Employee_Name,
case when a.Date = dateadd(:basedate, interval 7*0 day) then min(a.Attendance) end as d0 /* d for data? */
case when a.Date = dateadd(:basedate, interval 7*1 day) then min(a.Attendance) end as d1
case when a.Date = dateadd(:basedate, interval 7*2 day) then min(a.Attendance) end as d2
case when a.Date = dateadd(:basedate, interval 7*3 day) then min(a.Attendance) end as d3
dateadd(:basedate, interval 7*0 day) as week0
dateadd(:basedate, interval 7*1 day) as week1
dateadd(:basedate, interval 7*2 day) as week2
dateadd(:basedate, interval 7*3 day) as week3
from
attendance as a inner join employee as e ...
where a.Date between :basedate and dateadd(:basedate, interval 7*3 day)
group by
a.Employee_ID
You could pass in a :basedate parameter and offset a fixed number of weeks from that point. (I don't know what's the parameter convention for PHP and MySQL.) This will work if you can fix your results to a set number of weeks.
Pick out the dates from the first row to build the header and then build the rest of the table as you normally would. Yes there's some redundant data but there's no easy way to alias the columns with the dates themselves.
Following query you can use to gain the shown output along with a bit of PHP application
SELECT E.Name, A.Date, A.Attendance
FROM attendance AS A
INNER JOIN employee AS E
ON A.Employee_ID = E.Employee_ID
ORDER BY A.Date, E.Name
For implementing this in PHP
<?php
if (!$link = mysql_connect('< mysql_host >', '< mysql_user >', '< mysql_password >')) {
echo 'Could not connect to mysql';
exit;
}
if (!mysql_select_db('< mysql_dbname >', $link)) {
echo 'Could not select database';
exit;
}
$sql = 'SELECT E.Name, A.Date, A.Attendance '.
'FROM attendance AS A '.
'INNER JOIN employee AS E '.
'ON A.Employee_ID = E.Employee_ID '.
'ORDER BY E.Name, A.Date';
$result = mysql_query($sql, $link);
if (!$result) {
echo "DB Error, could not query the database\n";
echo 'MySQL Error: ' . mysql_error();
exit;
}
$name = '';
$resultArray = array();
$attendance = array();
foreach ($query as $row) {
if (isset($attendance[$row['Name']])) {
array_push($attendance[$row['Name']], $row['Date'] => $row['Attendance']);
} else {
$attendance[$row['Name']] = array($row['Date'] => $row['Attendance']);
}
}
print_r($attendance);
mysql_free_result($result);
?>
You would get an a associative array like this
Array(
"Diane" => Array("2015-02-07" => 'P', "2015-02-14" => 'P'),
"Robert" => Array("2015-02-07" => 'P', "2015-02-14" => 'P'),
"Karine" => Array("2015-02-07" => 'L', "2015-02-14" => 'L')
)
Now you can use this associative array to in a loop to render these elements in the Web page
Hope this helps...

MySQL Replace string SUM then total

Looking to get a total for each ID from the sum of the replacement fields.
SELECT
insurance_carrier as ID, SUM(REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','')) AS es_reserve,
SUM(REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-',''))AS structure_reserve,
SUM(es_reserve+structure_reserve) AS total
FROM job_tbl
WHERE
job_status NOT IN(2,4,6,7,9) AND
insurance_carrier !=0 AND
FROM_UNIXTIME(date_of_loss,'%m') = MONTH(NOW()) AND
FROM_UNIXTIME(date_of_loss,'%Y') = YEAR(NOW())
GROUP BY insurance_carrier
I get the results from es_reserve and structure_reserve but the total is 0.
BTW the fields contain items like $2,300- that's the reason for the replace
Any help would be appreciated!!!
EDIT: here is the results this produces
Array
(
[ID] => 14
[es_reserve] => 5000
[structure_reserve] => 35000
)
Array
(
[ID] => 15
[es_reserve] => 2500
[structure_reserve] => 2500
)
Array
(
[ID] => 41
[es_reserve] => 2500
[structure_reserve] => 2500
)
Array
(
[ID] => 44
[es_reserve] => 2500
[structure_reserve] =>
)
Here is what I would like it to produce
Array
(
[ID] => 14
[es_reserve] => 5000
[structure_reserve] => 35000
[total] => 40000
)
Array
(
[ID] => 15
[es_reserve] => 2500
[structure_reserve] => 2500
[total] => 5000
)
Array
(
[ID] => 41
[es_reserve] => 2500
[structure_reserve] => 2500
[total] => 5000
)
Array
(
[ID] => 44
[es_reserve] => 2500
[structure_reserve] =>
[total] => 2500
)
Total column is doing sum on original column value , the alias name defined in the select won't be used in the same select.
You can repeat replace statement while doing total column computation
SUM( REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','')
+ REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-',''))
Total,
instead of
SUM(es_reserve+structure_reserve) as total
The query becomes, with order by as asked in comment.
SELECT insurance_carrier as ID, SUM(REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','')) AS es_reserve, SUM(REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-',''))AS structure_reserve, SUM( REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','') + REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-','')) as Total FROM job_tbl WHERE job_status NOT IN(2,4,6,7,9) AND insurance_carrier !=0 AND FROM_UNIXTIME(date_of_loss,'%m') = MONTH(NOW()) AND FROM_UNIXTIME(date_of_loss,'%Y') = YEAR(NOW()) GROUP BY insurance_carrier
order by SUM( REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','') + REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-','')) desc
OR
use it as subquery
SELECT T.*, SUM(es_reserve+structure_reserve) AS total
FROM
(
SELECT
insurance_carrier as ID, SUM(REPLACE(REPLACE(REPLACE(es_reserve,'$',''),',',''),'-','')) AS es_reserve,
SUM(REPLACE(REPLACE(REPLACE(structure_reserve,'$',''),',',''),'-',''))AS structure_reserve
FROM job_tbl
WHERE
job_status NOT IN(2,4,6,7,9) AND
insurance_carrier !=0 AND
FROM_UNIXTIME(date_of_loss,'%m') = MONTH(NOW()) AND
FROM_UNIXTIME(date_of_loss,'%Y') = YEAR(NOW())
GROUP BY insurance_carrier
) T

sql query to set year as column name

By writing the following query
SELECT item_name, YEAR( DATE ) , SUM( item_sold_qty )
FROM item
JOIN sales ON item.id = sales.item_number
GROUP BY YEAR( DATE ) , item_name
ORDER BY item_name
i'm able to get the following result
item_name YEAR( DATE ) SUM( item_sold_qty )
pencil 2011 22
pencil 2012 44
eraser 2012 22
eraser 2011 11
pen 2012 66
pen 2011 33
nib 2012 88
nib 2011 44
Instead i want the result in the following way
item_name 2011 2012
pencil 22 44
eraser 11 22
pen 33 66
nib 44 88
I'm not really good at sql and have no clue for how to set the years as column names.
Need help.
NOTE :: My database has 2 tables. Sales table has date column which has different dates like 2012-03-01, 2012-04-02, 2011-07-03, so on...
Maybe something like this:
SELECT
item_name,
SUM(CASE WHEN YEAR( DATE )=2011 THEN item_sold_qty ELSE 0 END) AS '2011',
SUM(CASE WHEN YEAR( DATE )=2012 THEN item_sold_qty ELSE 0 END) AS '2012'
FROM
item
JOIN sales ON item.id = sales.item_number
GROUP BY
item_name
ORDER BY
item_name
EDIT
If you want the other years and still sum them. Then you can do this:
SELECT
item_name,
SUM(CASE WHEN YEAR( DATE )=2011 THEN item_sold_qty ELSE 0 END) AS '2011',
SUM(CASE WHEN YEAR( DATE )=2012 THEN item_sold_qty ELSE 0 END) AS '2012',
SUM(CASE WHEN NOT YEAR( DATE ) IN (2011,2012) THEN item_sold_qty ELSE 0 END) AS 'AllOtherYears'
FROM
item
JOIN sales ON item.id = sales.item_number
GROUP BY
item_name
ORDER BY
item_name
EDIT2
If you have a lot of years and you do not want to keep on adding years. Then you need to using dynamic sql. That means that you concat a varchar of the sql and then execute it.
Useful References:
MySQL pivot table with dynamic headers based on single column data
How To have Dynamic SQL in MySQL Stored Procedure
MySQL/Pivot table
MYSQL - Rows to Columns
The answer above will work but adding a case for ever year may or may not be suitable.
If you're on a PHP platform you could change the layout of your existing array like such
foreach($items as $item)
{
$item_names[$item[item_name]][$item[year]] += $item[item_sold_qty];
}
This will make an array as follows:
Array
(
[pencil] => Array
(
[2011] => 22
[2012] => 44
)
[eraser] => Array
(
[2012] => 22
[2011] => 11
)
[pen] => Array
(
[2012] => 66
[2011] => 33
)
[nib] => Array
(
[2012] => 88
[2011] => 44
)
)
Also change your original query to assign better names to the variables:
SELECT item_name, YEAR( DATE ) as year , SUM( item_sold_qty ) as item_sold_qty
FROM item
JOIN sales ON item.id = sales.item_number
GROUP BY YEAR( DATE ) , item_name
ORDER BY item_name
The above assumes your mysql result array looks something like this:
Array
(
[0] => Array
(
[item_name] => pencil
[year] => 2011
[item_sold_qty] => 22
)
[1] => Array
(
[item_name] => pencil
[year] => 2012
[item_sold_qty] => 44
)
[2] => Array
(
[item_name] => eraser
[year] => 2012
[item_sold_qty] => 22
)
[3] => Array
(
[item_name] => eraser
[year] => 2011
[item_sold_qty] => 11
)
[4] => Array
(
[item_name] => pen
[year] => 2012
[item_sold_qty] => 66
)
[5] => Array
(
[item_name] => pen
[year] => 2011
[item_sold_qty] => 33
)
[6] => Array
(
[item_name] => nib
[year] => 2012
[item_sold_qty] => 88
)
[7] => Array
(
[item_name] => nib
[year] => 2011
[item_sold_qty] => 44
)
)
Here:
SELECT
i.item_name,
SUM(s1.item_sold_qty) AS '2011',
SUM(s2.item_sold_qty) AS '2012'
FROM item i
LEFT JOIN sales s1 ON (i.id = s1.item_number AND YEAR(s1.DATE) = 2011)
LEFT JOIN sales s2 ON (i.id = s2.item_number AND YEAR(s2.DATE) = 2012)
GROUP BY i.item_name
ORDER BY i.item_name
Of course, you will have to add as many joins as many years you want to search through...