Create multiple categories with parent, child and grandchild - mysql

I want to create multiple categories with parent, child and grandchild.
And can order by ordering field.
id | parent_id | name | ordering
--------------------------------------
1 | 0 | Men | 1
2 | 0 | Women | 2
3 | 1 | Shoes | 3
4 | 2 | Watches | 4
5 | 1 | Pants | 5
6 | 3 | Sport | 6
7 | 3 | Casual | 7
8 | 2 | Book | 8
I want this result
Men
Shoes
Sport
Casual
Pants
Women
Watches
Book
Array out put
Array
(
[0] => Array
(
[id] => 1
[parent_id] => 0
[name] => Men
[ordering] => 1
[level] => parent //NEEDED
)
[1] => Array
(
[id] => 2
[parent_id] => 0
[name] => Women
[ordering] => 2
[level] => parent //NEEDED
)
[2] => Array
(
[id] => 3
[parent_id] => 1
[name] => Shoes
[ordering] => 3
[level] => child //NEEDED
)
[3] => Array
(
[id] => 4
[parent_id] => 2
[name] => Watches
[ordering] => 4
[level] => child //NEEDED
)
[4] => Array
(
[id] => 5
[parent_id] => 1
[name] => Pants
[ordering] => 5
[level] => child //NEEDED
)
[5] => Array
(
[id] => 6
[parent_id] => 3
[name] => Sport
[ordering] => 6
[level] => grandchild //NEEDED
)
[6] => Array
(
[id] => 7
[parent_id] => 3
[name] => Casual
[ordering] => 7
[level] => grandchild //NEEDED
)
[7] => Array
(
[id] => 8
[parent_id] => 2
[name] => Book
[ordering] => 8
[level] => child //NEEDED
)
)

This could be a solution to get your level information:
SELECT CASE WHEN parent_id = 0 THEN 'Parent'
ELSE CASE WHEN (SELECT T2.parent_id
FROM tab T2
WHERE T2.id = T.parent_id) = 0 THEN 'Child'
ELSE 'Grandchild'
END
END AS level
FROM tab T
Fiddle here
To put the content of this SQL into an array you need a server side language like PHP, since you're not using mongoDB or similar.

Assuming your table is called "items", you could do the following recursive query to generate names containing the parent and the ordering attribute, then order by the generated name and add spaces before the name according to the level:
;WITH itemsHierarchy (id, parent_id, name, generatedname, level)
AS
(
SELECT
i.id,
i.parent_id,
i.name,
CAST(i.name AS varchar(MAX)) as generatedname,
1 as level
FROM items i
WHERE i.parent_id = 0
UNION ALL
SELECT
i.id,
i.parent_id,
i.name,
CAST(ih.generatedname + '_' + CAST(i.ordering as varchar(2))+ '_' + i.name AS varchar(MAX)),
ih.level + 1
FROM items i
INNER JOIN itemsHierarchy ih ON i.parent_id = ih.id
)
SELECT REPLICATE(' ', level) + name
FROM itemsHierarchy
ORDER BY generatedname
Result:
Men
Shoes
Sport
Casual
Pants
Women
Watches
Book

Finally i found good answer
ref : Parent child mysql
select t0.*,
concat(
case coalesce(t4.parent_id, 0)
when 0 then ''
else concat(cast(t4.parent_id as char), '\\')
end,
case coalesce(t3.parent_id, 0)
when 0 then ''
else concat(cast(t3.parent_id as char), '\\')
end,
case coalesce(t2.parent_id, 0)
when 0 then ''
else concat(cast(t2.parent_id as char), '\\')
end,
case coalesce(t1.parent_id, 0)
when 0 then ''
else concat(cast(t1.parent_id as char), '\\')
end,
case coalesce(t0.parent_id, 0)
when 0 then ''
else concat(cast(t0.parent_id as char), '\\')
end,
cast(t0.id as char)
) as path
from mytable t0
left join mytable t1 on t0.parent_id = t1.Id
left join mytable t2 on t1.parent_id = t2.Id
left join mytable t3 on t2.parent_id = t3.Id
left join mytable t4 on t3.parent_id = t4.Id
order by
concat(
case coalesce(t4.parent_id, 0)
when 0 then ''
else concat(cast(t4.parent_id as char), '\\')
end,
case coalesce(t3.parent_id, 0)
when 0 then ''
else concat(cast(t3.parent_id as char), '\\')
end,
case coalesce(t2.parent_id, 0)
when 0 then ''
else concat(cast(t2.parent_id as char), '\\')
end,
case coalesce(t1.parent_id, 0)
when 0 then ''
else concat(cast(t1.parent_id as char), '\\')
end,
case coalesce(t0.parent_id, 0)
when 0 then ''
else concat(cast(t0.parent_id as char), '\\')
end,
cast(t0.id as char)
)

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

Altering a query to consolidate answers in a poll

I have the following mysql query:
SELECT p.id, p.title, p.description, a.id, a.answer, q.id, q.question
FROM x_trybe_poll_relation pr
LEFT JOIN x_polls p
ON pr.poll_id = p.id
LEFT JOIN x_polls_question_relation qr
ON p.id = qr.poll_id
LEFT JOIN x_polls_questions q
ON qr.question_id = q.id
LEFT JOIN x_polls_answers a
ON q.id = a.question_id
WHERE pr.trybe_id = '%s'
Which returns:
[polls] => Array
(
[0] => Array
(
[id] => 79de13af1978ab14f56b4305956b2d93cd42e0fb
[title] => Poll 1
[description] => Poll 1 Description
[answer] => Danny Welbeck
[question] => Who is the best player in the Arsenal squad?
)
[1] => Array
(
[id] => 79de13af1978ab14f56b4305956b2d93cd42e0fb
[title] => Poll 1
[description] => Poll 1 Description
[answer] => Alexis Sanchez
[question] => Who is the best player in the Arsenal squad?
)
)
How do I adjust the mysql query to get the following:
[polls] => Array
(
[0] => Array
(
[id] => 79de13af1978ab14f56b4305956b2d93cd42e0fb
[title] => Poll 1
[description] => Poll 1 Description
[answers] => Array (
[0] => Array (
[id] => abc
[answer] => Danny Welbeck
)
[1] => Array (
[id] => def
[answer] => Alexis Sanchez
)
)
[question] => Who is the best player in the Arsenal squad?
)
)
I want to get the poll question, and get the array of pre-generated answers with one query.
Is this possible, or should I just run two queries?
Thanks

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

mysql union and group by similar fields

Here is my query (I replaced table names with generic ones). I am trying to do a union all on two different queries in order to group them all by date so that results with similar dates come out as one row.
I am getting the "Every derived table must have its own alias" error when attempting to execute. What am I typing in wrong?
I have researched this but couldn't find the answer. Every selected field has an alias? Or is the issue in the first SELECT?
SELECT SUM(val), id, dat, title FROM (
SELECT table1.product_id as id, SUM(table1.qty) as val, DATE_FORMAT(table1.created, '%Y-%m-1') as dat, table2.title as title
FROM table1
LEFT JOIN table3 ON table1.event_id = table3.id
LEFT JOIN table2 ON table1.product_id = table2.id
WHERE table1.user_id = $user_id AND table3.active != 2 AND table3.temp = 0 AND table2.active != 2
GROUP BY dat
UNION ALL
SELECT table4.product_id as id, SUM(table4.qty) as val, DATE_FORMAT(table4.created, '%Y-%m-1') as dat, table2.title as title
FROM table4
LEFT JOIN table5 ON table4.festival_id = table5.id
LEFT JOIN table2 ON table4.product_id = table2.id
WHERE table4.user_id = $user_id AND table5.active != 2 AND table2.active != 2
GROUP BY dat
)
GROUP BY id
ORDER BY dat ASC
Here is what I am attempting to do:
My original result:
Array
(
[0] => stdClass Object
(
[id] => 1
[val] => 1
[dat] => 2012-05-1
[title] => Test Product
)
[1] => stdClass Object
(
[id] => 1
[val] => 8
[dat] => 2012-06-1
[title] => Test Product
)
[2] => stdClass Object
(
[id] => 2
[val] => 4
[dat] => 2012-06-1
[title] => Test Product 2
)
[3] => stdClass Object
(
[id] => 3
[val] => 6
[dat] => 2012-06-1
[title] => Test Product 3
)
[4] => stdClass Object
(
[id] => 1
[val] => 10
[dat] => 2012-05-1
[title] => Test Product
)
[5] => stdClass Object
(
[id] => 1
[val] => 8
[dat] => 2012-06-1
[title] => Test Product
)
[6] => stdClass Object
(
[id] => 2
[val] => 3
[dat] => 2012-06-1
[title] => Test Product 2
)
[7] => stdClass Object
(
[id] => 3
[val] => 3
[dat] => 2012-06-1
[title] => Test Product 3
)
)
So if they have a similar date and ID, I need those to be just one result. Like so:
Array
(
[0] => stdClass Object
(
[id] => 1
[val] => 11
[dat] => 2012-05-1
[title] => Test Product
)
[1] => stdClass Object
(
[id] => 1
[val] => 8
[dat] => 2012-06-1
[title] => Test Product
)
[2] => stdClass Object
(
[id] => 2
[val] => 7
[dat] => 2012-06-1
[title] => Test Product 2
)
[3] => stdClass Object
(
[id] => 3
[val] => 9
[dat] => 2012-06-1
[title] => Test Product 3
)
)
Please let me know if you need anything else. Thanks in advance.
Try this:
SELECT SUM(val), id, dat, title FROM (
SELECT table1.product_id as id, SUM(table1.qty) as val, DATE_FORMAT(table1.created, '%Y-%m-1') as dat, table2.title as title
FROM table1
LEFT JOIN table3 ON table1.event_id = table3.id
LEFT JOIN table2 ON table1.product_id = table2.id
WHERE table1.user_id = $user_id AND table3.active != 2 AND table3.temp = 0 AND table2.active != 2
GROUP BY dat
UNION ALL
SELECT table4.product_id as id, SUM(table4.qty) as val, DATE_FORMAT(table4.created, '%Y-%m-1') as dat, table2.title as title
FROM table4
LEFT JOIN table5 ON table4.festival_id = table5.id
LEFT JOIN table2 ON table4.product_id = table2.id
WHERE table4.user_id = $user_id AND table5.active != 2 AND table2.active != 2
GROUP BY dat
) AS t
GROUP BY id, dat
ORDER BY dat ASC
As the error suggests, every view/derived table must have an alias..
Edit: This will give you records with distinct id/dat pair. Seems this is what is you are after.