Mysql tree traverse and count - php

I`ve got the following table in mysql
id|top_id|amount
1 NULL 2
2 NULL 8
3 NULL 4
4 3 7
5 2 8
6 2 4
7 5 5
8 7 1
9 6 6
10 8 6
For the first 3 ids i need to sum up all amounts of its successors to get the following:
id | amount
1 8
2 32
3 11
I guess there should be joins but unfortunately I can`t get the working mysql request. Can somebody help me?
UPD: In php I have the following query:
$tops = $mysqli->query('SELECT * FROM table WHERE top_id IS NULL')
which obviously returns me just 3 top ids and their plain amounts (2, 8 and 4 respectively). Instead of 2, 8 and 4 I need to get 12, 28 and 11 and that`s the problem((

This is the crudest solution... No doubt someone will provide some hints for a more scalable solution shortly (perhaps employing PHP)...
SELECT a.id
, COALESCE(a.amount,0)
+ COALESCE(b.amount,0)
+ COALESCE(c.amount,0)
+ COALESCE(d.amount,0)
+ COALESCE(e.amount,0)
+ COALESCE(f.amount,0) total
FROM my_table a
LEFT
JOIN my_table b
ON b.top_id = a.id
LEFT
JOIN my_table c
ON c.top_id = b.id
LEFT
JOIN my_table d
ON d.top_id = c.id
LEFT
JOIN my_table e
ON e.top_id = d.id
LEFT
JOIN my_table f
ON f.top_id = e.id
WHERE a.top_id IS NULL;

Related

codeigniter: get percentage in multiple table by data category

I have tables like this,
table_a
PID Name Type
1 a selling
2 b sampling
3 c selling
4 d sampling
5 e selling
And,
table_b
ID PID Qty
1 2 3
2 2 2
3 1 1
4 3 1
5 1 3
6 5 3
7 4 3
8 3 2
I need to show like this,
output_selling
Name Total_qty Percentage
a 4 40%
c 3 30%
e 3 30%
And,
output_sampling
Name Total_qty Percentage
b 5 62,5%
d 3 37,5%
How would I go about this in CodeIgniter?
You can use below in your function and change 'sampling' and 'selling' as you need it:
$this->db->query("
SELECT dd.NAME,
dd.total_qty,
( dd.total_qty / dd.totals ) * 100 AS Percentage
FROM (SELECT a.NAME,
Sum(b.qty) AS Total_qty,
(SELECT Sum(b1.qty) AS total
FROM table_b b1
JOIN table_a a1
ON a1.pid = b1.pid
AND a1.type = 'selling') AS totals
FROM table_a a
JOIN table_b b
ON b.pid = a.pid
AND a.type = 'selling'
GROUP BY a.pid) dd ");
Please see below query output:

How to Get Newest Data with `created_at` Column

How can I query the data where id_konsul = 4, and how can I get the latest staflow from created_at if it is the same?
example
id id_konsul staflow created_at
1 4 1 21/05/2018 11.03
2 4 2 22/05/2018 11.03
3 4 3 23/05/2018 11.03
4 4 4 24/05/2018 11.03
5 4 5 25/05/2018 11.03
6 4 6 26/05/2018 11.03
7 4 7 27/05/2018 11.03
8 4 6 28/05/2018 11.03
9 4 7 29/05/2018 11.03
10 4 7 30/05/2018 11.03
11 4 8 31/05/2018 11.03
than i get this
id id_konsul staflow created_at
1 4 1 21/05/2018 11.03
2 4 2 22/05/2018 11.03
3 4 3 23/05/2018 11.03
4 4 4 24/05/2018 11.03
5 4 5 25/05/2018 11.03
8 4 6 28/05/2018 11.03
10 4 7 30/05/2018 11.03
11 4 8 31/05/2018 11.03
try this query
SELECT * FROM test1 n
WHERE created_at=(SELECT MAX(created_at)FROM test1
WHERE staflow=n.staflow)
order by id
To get latest row per staflow attribute you can use a self join
select a.*
from demo a
join (
select id_konsul,staflow, max(created_at) created_at
from demo
where id_konsul = 4
group by id_konsul, staflow
) b on a.staflow = b.staflow
and a.id_konsul = b.id_konsul
and a.created_at = b.created_at;
Or using a left join
select a.*
from demo a
left join demo b on a.id_konsul = b.id_konsul
and a.staflow = b.staflow
and a.created_at < b.created_at
where a.id_konsul = 4
and b.id_konsul is null
Demo
To write above queries using laravel's query builder you can use following references
Laravel Eloquent select all rows with max created_at
Laravel - Get the last entry of each UID type
Laravel Eloquent group by most recent record
Please try this query.
SELECT * FROM table_name WHERE id_konsul = 4 ORDER BY created_at DESC LIMIT 1;
You can user INNER JOIN.
Example:
SELECT t0.* from {TABLE_NAME} AS t0 INNER JOIN {TABLE_NAME} t1 ON t0.staflow = t1.staflow WHERE t0.created_at > t1.created_at and t0.id_konsul = 4

Mysql Where Column A = X and Column B = Y and or Column B = Z

I'm trying to get a set of values from a pivot table where column A is equal to an array of values, so for example ID 12 has attribute_value_id equal to 3 and 9. Can this be done? I've got this far...
ID | post_id | attribute_id | attribute_value_id
8 12 1 3
9 12 2 13
10 13 1 3
11 13 2 9
12 16 1 3
13 16 2 9
88 11 1 1
89 11 2 8
90 11 3 18
91 11 4 22
The query...
select *
from `searching_for_posts`
where (
select count(*)
from `attributes`
inner join `searching_for_attributes`
on `attributes`.`id` = `searching_for_attributes`.`attribute_id`
where `searching_for_attributes`.`searching_for_post_id` = `searching_for_posts`.`id`
and (`attribute_value_id` = 3 and `attribute_value_id` = 9)
) >= 1
If I use the and then I get no values. If I use the or then I get 3 values but it should return 2. I have limited SQL experience.
You can do this using group by and having. Your logic is hard to follow, but it is something like this:
select post_id
from table t
where attribute_value_id in (3, 9)
group by post_id
having count(distinct attribute_id) = 2;
I would think you would want to check on attribute_id as well, but that doesn't seem to be part of the question.
EDIT:
If these are stored in another table:
select a.post_id
from attributes a join
searching_for_attributes sfa
on a.attribute_id = sfa.attribute_id and
a.attribute_value_id = sfa.attribute_value_id
group by a.post_id
having count(*) = (select count(*) from searching_for_attributes);
In response to #GordonLinoff answer, I've managed to use GROUP BY and HAVING COUNT to get the desired data. Here's what I came up with and hope this helps someone else...
select *
from `searching_for_posts`
where (
select count(*)
from `attributes`
inner join `searching_for_attributes` on `attributes`.`id` = `searching_for_attributes`.`attribute_id`
where `searching_for_attributes`.`searching_for_post_id` = `searching_for_posts`.`id`
and `attribute_value_id` in (3, 9)
having count(distinct `attributes`.`id`) = 2
) >= 1
group by `id`

mysql left join with two table

Assuming I have 2 tables:
leave_type
id name
1 maternity leave
2 Medical leave
3 Casual Leave
4 Sick Leave
5 honeymoon Leave
employee_leave_blance
id employee_id year leave_type_id val
1 4 2015 1 9
2 4 2015 2 5
3 8 2015 1 10
4 4 2015 3 4
Here employee_leave_blance.leave_type_id = leave_type.id
Now I want to get all Leave Type values for employee_id=4
In employee_leave_blance table for employee_id=4 there are only 3 leave_type entries but in leave_type table there are 5 of them.
I want to get 5 entries for a employee. If no entry is found in employee_leave_blance it should return 0.
Let me give an example: I want to get output for employee_id = 4
employee_id name val
4 maternity leave 9
4 Medical leave 5
4 Casual Leave 4
4 Sick Leave 0
4 honeymoon Leave 0
For this I've tried following query:
select
el.employee_id, lt.name, el.val from leave_type as lt
left join employee_leave_blance as el on el.leave_type_id = lt.id
where
el.year = YEAR(CURDATE()) and el.employee_id = 4
It however returns following results:
employee_id name val
4 maternity leave 9
4 Medical leave 5
4 Casual Leave 4
Now how can I get values for all leave_type for an employee?
Not sure if this is what you need, please try :
select ifnull(el.employee_id,4) as employee_id,
lt.name,ifnull(el.val,0) as val
from leave_type as lt
left join (select year,employee_id,val,leave_type_id
from employee_leave_balance) as el
on el.leave_type_id = lt.id
and el.year = year(curdate())
and el.employee_id = 4
Actually, your query would works with some modification. just remove where clause to and because you already joined tables and use ifnull function to return 0 for null values. This is your query with some improvement :
select
ifnull(el.employee_id,4) as employee_id, lt.name, ifnull(el.val,0) as val
from leave_type as lt
left join employee_leave_balance as el on el.leave_type_id = lt.id
and
el.year = YEAR(CURDATE()) and el.employee_id = 4

confusing in mysql database tables

i am bit confuse in to getting the result into the two tables, i know it is simple but not getting any clue..
here is my query the gives me the result, but when i am using the group by then it's just giving me the result of one line even the actual result in database is (300, 500) because i am fetching the result through the lead_id which is common in both tables..
SELECT inv.amount, crmd.computers, crmd.product_id, crmd.pc_opti
FROM invoice AS inv, lead_crm_data AS crmd
WHERE inv.lead_id = '310'
AND crmd.lead_id = '310'
GROUP BY inv.lead_id
here is the result of the given query..
amount computers product_id pc_opti
300 2 7, 6 2
300 3 7, 6 3
540 2 7, 6 2
540 3 7, 6 3
result with GROUP BY
300 2 7, 6 2
Desired REsult
300 2 7, 6 2
540 3 7, 6 3
Try this:
SELECT inv.amount, crmd.computers, crmd.product_id, crmd.pc_opti
FROM invoice AS inv, lead_crm_data AS crmd
WHERE inv.lead_id = '310'
AND crmd.lead_id = '310'
GROUP BY inv.amount
You could use a better (IMHO) syntax:
SELECT inv.amount, crmd.computers, crmd.product_id, crmd.pc_opti
FROM invoice AS inv INNER JOIN lead_crm_data AS crmd
ON inv.lead_id = crmd.lead_id
AND inv.lead_id = '310'
GROUP BY inv.amount

Categories