Count total child node on left and right grouped by ranks - mysql

I am working on a project that rewards people base on referrals (MLM)
I have been able to count the total number of child nodes on both left and right side but now I need to be able to update the ranks of users when they have a certain number of users with certain ranks below them on both sides. (I will explain better below:
User Table
id | name | parentID| side | rank |
4 | Dan | | | starter|
5 | Chris | 4 | left | starter|
6 | James | 4 | right| starter|
7 | Tybe | 5 | left | starter|
8 | Rose | 5 | right| starter|
9 | Paul | 6 | left | starter|
10 | Zach | 6 | right| starter|
Tree table
userID | left | right| leftCount | rightCount|
4 | 5 | 6 | 3 | 3 |
5 | 7 | 8 | 1 | 1 |
6 | 9 | 10 | 1 | 1 |
7 | | | 0 | 0 |
8 | | | 0 | 0 |
9 | | | 0 | 0 |
10 | | | 0 | 0 |
Below is the tree generated from this table
How i update the leftCount and rightCount when a user registers
$referralid; //who is referring the current user
$side; //the side the user is to fall under, either left or right
$temp_referralid = $referralid;
$temp_sideCount = $side.'Count'; //leftCount or rightCount
$temp_side = $side;
$total_count=1;
$i=1;
while($total_count>0){
$stmt = $db->prepare("SELECT * from tree WHERE id=:id");
$stmt->bindValue(':id', $temp_referralid);
$stmt->execute();
$r = $stmt->fetch(PDO::FETCH_ASSOC);
$current_temp_sideCount = ($r[$temp_sideCount]+1);
//This will add (+1) to the leftCount or rightCount
//of the referral depending on the side the user
//choose to fall under.
$sql ="UPDATE `tree` SET `$temp_sideCount`=:count WHERE `id` = :id";
$stmt = $db->prepare($sql);
$stmt->bindValue(':count', $current_temp_sideCount);
$stmt->bindValue(':id', $temp_referralid);
$stmt->execute();
//if the user has someone that referred them as
//only the last person at the top has no referral
if($temp_referralid!=""){
//change the $referralid to the person that referred the person
//referring this user. this is where the loop will go through
//to the last person maintaining the side upward
$next_referralid = $this->getReferringId($db, $temp_referralid);
$temp_side = $this->getReferringIdSide($db, $temp_referralid);
$temp_sideCount = $temp_side.'Count';
$temp_referralid = $next_referralid;
$i++;
}else{
$total_count=0;
}
}
}
Functions used
getReferringId($db, $id) //gets the referringId of the user passed as
//param from the user table
getReferringIdSide($db, $id) //gets the side which the user
//is on (left or right) from the user table
All this is working just fine but then I need to implement something and I haven’t found the best way around it.
I need to keep changing the rank for each user if they have attained a stage. see below and example:
stage 1: starter //just registered
stage 2: grow // the person has leftCount=3 and rightCount=3
stage 3: growbig //the person has 7 - grow user on the left
//and 7- grow user on the right
state 4: growbigger //the person has 7 - growbig on left and 7 growbig
//on the right
Up to stage 2, I have no problem but upwards is where I cant get my hands on the right logic
Update
for example: The numbers of growbig's can come from anywhere on the legs, it shouldn’t just be direct nodes, just a count of ranks all below that user on each sides
UPDATE: Re-asking in a clearer term and specifications
its a binary tree (2:2) which means a person can only have two people directly under them (one on the left and another on the right.
With the picture above my table looks like this
Tree table
userID | left (userid) | right (userid)| rank
8 | 4 | 12 |
4 | 2 | 6 |
12 | 10 | 14 |
2 | 1 | 3 |
6 | 5 | 7 |
10 | 9 | 11 |
14 | 14 | 15 |
Note: its not compulsory for a user to have anyone under him on any side or both. it means if a user have nobody under him then the tree (branch) ends there, if he has one person directly on the left and none on the right it means the left branch can continue to grow.
The logic to grade each user base on their growths and how they have managed to balance the growth on each side is the problem.
The logic
Rank 1: supervisor: user must have at 3 users on its right branch and 3 users on the left branch.
Rank 2: controller: user must have 7 users who are 'supervisors' on it's left and 7 users who have become supervisors on the right too.
Rank 3: Senior Controller: user must have 7 users who are 'controller' on the left branch and have 7 'controller' on the right too.
Rank 4: Ambassador: user must have 7 users who are senior controller on its left and 7 senior controllers on the right
Rank 5: Senior Ambassador: user must have 7 users who are ambassadors on the left and same on the right.
Rank 6: Grand Ambassador: user must have 7 users who are senior ambassadors on his both sides.
Explanation:
let me pick on rank and explain it:
Rank: Ambassador- if user with ID 3 has 45 people on its right hand side and 7 of the people on its right branch are senior controllers and also on the left he has 67 people and 7 are already senior controllers then user with ID 3 should be upgraded to 'ambassador'
#blag

This is more likely how I would take this problem (using http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ ):
The new table schema is :
'id'| 'name' | 'left'| 'right'| 'rank'
4 | 'Dan' | 1 | 14 | 'starter'
5 | 'Chris'| 2 | 7 | 'starter'
6 | 'James'| 8 | 13 | 'starter'
7 | 'Tybe' | 3 | 4 | 'starter'
8 | 'Rose' | 5 | 6 | 'starter'
9 | 'Paul' | 9 | 10 | 'starter'
10 | 'Zach' | 11 | 12 | 'starter'
The full version :
Note, I use the following value to avoid using a bigger dataset
-- on each side
set #grow = 1 // -- 1 child R & L
set #growbig = 2 // -- 2 grow child R & L
SQL Fiddle
PROCEDURE
CREATE PROCEDURE p(IN p_parent varchar(15), IN p_children varchar(15))
BEGIN
IF NOT EXISTS (
select parent.*, count(distinct dc.id) direct_child
from u parent
left join u as dc on(parent.left=dc.left-1 or parent.right=dc.right+1)
WHERE parent.name = p_parent
group by parent.id
having count(distinct dc.id) =2
)
THEN
SET #myLeft =(SELECT `left` FROM u WHERE name = p_parent);
UPDATE u SET `right` = `right` + 2 WHERE `right` > #myLeft;
UPDATE u SET `left` = `left` + 2 WHERE `left` > #myLeft;
INSERT INTO u(`name`, `left`, `right`)
VALUES(p_children, #myLeft + 1, #myLeft + 2);
END IF;
END
//
call p('Tybe','Marjorie') //
call p('Tybe','Vernon') //
call p('Rose','Marc') //
call p('Rose','Peter') //
call p('Marc','Lily') //
call p('Marc','Ignotus') //
call p('Ignotus','Aragorn') //
call p('Ignotus','Arwen') //
call p('Peter','Chase') //
call p('Peter','Foreman') //
call p('Chase','Pétunia') //
call p('Chase','Dudley') //
call p('Foreman','Bob') //
call p('Foreman','Taub') //
call p('Paul','Lisa') //
call p('Paul','Bilbo') //
call p('Lisa','House') //
call p('Lisa','Gandalf') //
call p('Gandalf','Frodo') //
call p('Gandalf','Legolas') //
call p('House','Thirteen') //
call p('House','Wilson') //
call p('Thirteen','Ginny') //
call p('Thirteen','Harry') //
call p('Wilson','Kutner') //
call p('Wilson','Master') //
call p('Master','Adams') //
call p('Master','Park') //
call p('Zach','Ary') //
grow
set #grow = 1 //
update u
set rank = 'grow'
where u.id in (
select id from (
select id
from (
select p.id id, p.name name, lc.id lcid, null rcid
from u p
inner join u l on (p.left = l.left-1 and p.right <> l.right+1)
inner join u lc on (lc.left >= l.left and lc.right <= l.right)
inner join u r on (p.right = r.right+1 and p.left <> r.left-1)
union all
select p.id id, p.name name, null lcid, rc.id rcid
from u p
inner join u l on (p.left = l.left-1 and p.right <> l.right+1)
inner join u r on (p.right = r.right+1 and p.left <> r.left-1)
inner join u rc on (rc.left >= r.left and rc.right <= r.right)
) p
group by p.id
having
count(distinct lcid) >= #grow
and count(distinct rcid) >= #grow
) z
)
//
growbig
set #growbig = 2 //
update u
set rank = 'growbig'
where u.id in (
select id from (
select id
from (
select p.id id, p.name name, lc.id lcid, null rcid
from u p
inner join u l on (p.left = l.left-1 and p.right <> l.right+1)
inner join u lc on (lc.rank ='grow' and lc.left >= l.left and lc.right <= l.right)
inner join u r on (p.right = r.right+1 and p.left <> r.left-1)
union all
select p.id id, p.name name, null lcid, rc.id rcid
from u p
inner join u l on (p.left = l.left-1 and p.right <> l.right+1)
inner join u r on (p.right = r.right+1 and p.left <> r.left-1)
inner join u rc on (rc.rank ='grow' and rc.left >= r.left and rc.right <= r.right)
) p
group by p.id
having
count(distinct lcid) >= #growbig
and count(distinct rcid) >= #growbig
) z
)
//
Query 1:
-- output parent that have both right and left child
select parent.*, count(distinct dc.id) direct_child
from u parent
left join u as dc on(parent.left=dc.left-1 or parent.right=dc.right+1)
group by parent.id
having count(distinct dc.id) =2
Results:
| id | name | left | right | rank | direct_child |
|----|----------|------|-------|---------|--------------|
| 4 | Dan | 1 | 72 | growbig | 2 |
| 5 | Chris | 2 | 35 | grow | 2 |
| 6 | James | 36 | 71 | grow | 2 |
| 7 | Tybe | 3 | 8 | grow | 2 |
| 8 | Rose | 9 | 34 | growbig | 2 |
| 9 | Paul | 37 | 66 | grow | 2 |
| 13 | Marc | 24 | 33 | grow | 2 |
| 14 | Peter | 10 | 23 | grow | 2 |
| 16 | Ignotus | 25 | 30 | grow | 2 |
| 19 | Chase | 17 | 22 | grow | 2 |
| 20 | Foreman | 11 | 16 | grow | 2 |
| 25 | Lisa | 40 | 65 | grow | 2 |
| 27 | House | 47 | 64 | grow | 2 |
| 28 | Gandalf | 41 | 46 | grow | 2 |
| 31 | Thirteen | 58 | 63 | grow | 2 |
| 32 | Wilson | 48 | 57 | grow | 2 |
| 36 | Master | 49 | 54 | grow | 2 |
Query 2:
-- show the tree
SELECT CONCAT( REPEAT('|...', COUNT(parent.name) - 1), node.id, ' ', node.name,' /',node.rank) AS name
FROM u AS node,
u AS parent
WHERE node.left BETWEEN parent.left AND parent.right
GROUP BY node.name
ORDER BY node.left
Results:
| name |
|-----------------------------------------------|
|4 Dan /growbig |
||...5 Chris /grow |
||...|...7 Tybe /grow |
||...|...|...12 Vernon /starter |
||...|...|...11 Marjorie /starter |
||...|...8 Rose /growbig |
||...|...|...14 Peter /grow |
||...|...|...|...20 Foreman /grow |
||...|...|...|...|...24 Taub /starter |
||...|...|...|...|...23 Bob /starter |
||...|...|...|...19 Chase /grow |
||...|...|...|...|...22 Dudley /starter |
||...|...|...|...|...21 Pétunia /starter |
||...|...|...13 Marc /grow |
||...|...|...|...16 Ignotus /grow |
||...|...|...|...|...18 Arwen /starter |
||...|...|...|...|...17 Aragorn /starter |
||...|...|...|...15 Lily /starter |
||...6 James /grow |
||...|...9 Paul /grow |
||...|...|...26 Bilbo /starter |
||...|...|...25 Lisa /grow |
||...|...|...|...28 Gandalf /grow |
||...|...|...|...|...30 Legolas /starter |
||...|...|...|...|...29 Frodo /starter |
||...|...|...|...27 House /grow |
||...|...|...|...|...32 Wilson /grow |
||...|...|...|...|...|...36 Master /grow |
||...|...|...|...|...|...|...38 Park /starter |
||...|...|...|...|...|...|...37 Adams /starter |
||...|...|...|...|...|...35 Kutner /starter |
||...|...|...|...|...31 Thirteen /grow |
||...|...|...|...|...|...34 Harry /starter |
||...|...|...|...|...|...33 Ginny /starter |
||...|...10 Zach /starter |
||...|...|...39 Ary /starter |
Query 3:
-- show parent + child data
select *,(l.right - l.left -1)/2 l , (r.right - r.left -1)/2 r from u p
inner join u l on (p.left = l.left-1 and p.right <> l.right+1)
inner join u r on (p.right = r.right+1 and p.left <> r.left-1)
Results:
| id | name | left | right | rank | id | name | left | right | rank | id | name | left | right | rank | l | r |
|----|----------|------|-------|---------|----|---------|------|-------|---------|----|----------|------|-------|---------|----|----|
| 4 | Dan | 1 | 72 | growbig | 5 | Chris | 2 | 35 | grow | 6 | James | 36 | 71 | grow | 16 | 17 |
| 5 | Chris | 2 | 35 | grow | 7 | Tybe | 3 | 8 | grow | 8 | Rose | 9 | 34 | growbig | 2 | 12 |
| 6 | James | 36 | 71 | grow | 9 | Paul | 37 | 66 | grow | 10 | Zach | 67 | 70 | starter | 14 | 1 |
| 7 | Tybe | 3 | 8 | grow | 12 | Vernon | 4 | 5 | starter | 11 | Marjorie | 6 | 7 | starter | 0 | 0 |
| 8 | Rose | 9 | 34 | growbig | 14 | Peter | 10 | 23 | grow | 13 | Marc | 24 | 33 | grow | 6 | 4 |
| 13 | Marc | 24 | 33 | grow | 16 | Ignotus | 25 | 30 | grow | 15 | Lily | 31 | 32 | starter | 2 | 0 |
| 16 | Ignotus | 25 | 30 | grow | 18 | Arwen | 26 | 27 | starter | 17 | Aragorn | 28 | 29 | starter | 0 | 0 |
| 14 | Peter | 10 | 23 | grow | 20 | Foreman | 11 | 16 | grow | 19 | Chase | 17 | 22 | grow | 2 | 2 |
| 19 | Chase | 17 | 22 | grow | 22 | Dudley | 18 | 19 | starter | 21 | Pétunia | 20 | 21 | starter | 0 | 0 |
| 20 | Foreman | 11 | 16 | grow | 24 | Taub | 12 | 13 | starter | 23 | Bob | 14 | 15 | starter | 0 | 0 |
| 9 | Paul | 37 | 66 | grow | 26 | Bilbo | 38 | 39 | starter | 25 | Lisa | 40 | 65 | grow | 0 | 12 |
| 25 | Lisa | 40 | 65 | grow | 28 | Gandalf | 41 | 46 | grow | 27 | House | 47 | 64 | grow | 2 | 8 |
| 28 | Gandalf | 41 | 46 | grow | 30 | Legolas | 42 | 43 | starter | 29 | Frodo | 44 | 45 | starter | 0 | 0 |
| 27 | House | 47 | 64 | grow | 32 | Wilson | 48 | 57 | grow | 31 | Thirteen | 58 | 63 | grow | 4 | 2 |
| 31 | Thirteen | 58 | 63 | grow | 34 | Harry | 59 | 60 | starter | 33 | Ginny | 61 | 62 | starter | 0 | 0 |
| 32 | Wilson | 48 | 57 | grow | 36 | Master | 49 | 54 | grow | 35 | Kutner | 55 | 56 | starter | 2 | 0 |
| 36 | Master | 49 | 54 | grow | 38 | Park | 50 | 51 | starter | 37 | Adams | 52 | 53 | starter | 0 | 0 |

Related

GROUP sum BY two tables by joining

I'm trying to write a SQL query that will correctly group sales items sold_qyt and sub-total-price together as per product's category so I can show this on the printable invoice that product from Jelly Sheet = 4 at a rate of 62 subtotal for this category product is 248(4 * 62 = 248). but when I try to run the below-mentioned query it shows out-put as 12 but I want subtotal and sold_qyt segregated base on category.
I have tried to run different queries just one query gives the output which is mentioned below and this is for just the sum of all sold_qyt. DB example is also shown below
DB Example: (For better understanding)
Table # 1:
Category
ID | code | name
1 | 1 | jelly sheet
2 | 2 | 9D Glass
3 | 3 | Polished Glass
Table # 2:
Product:
ID | code | name | cost | category_id | price
1 | 1 | IP11JS | 50 | 1 | 62
2 | 2 | IP12JS | 50 | 1 | 62
3 | 3 | IP119D | 40 | 2 | 55
4 | 4 | IP129D | 40 | 2 | 55
5 | 5 | IP11PG | 18 | 3 | 25
6 | 6 | IP12PG | 18 | 3 | 25
Table # 3:
sale_items:
ID | sale_id | product_id | product_code | product_name | unit_price | sold_qyt | subtotal |
1 | 1 | 1 | 1 | IP11JS | 62 | 2 | 124 |
2 | 1 | 2 | 2 | IP12JS | 62 | 2 | 124 |
3 | 1 | 3 | 3 | IP119D | 55 | 2 | 110 |
4 | 1 | 4 | 4 | IP129D | 55 | 2 | 110 |
5 | 1 | 5 | 5 | IP11PG | 25 | 2 | 50 |
6 | 1 | 6 | 6 | IP12PG | 25 | 2 | 50 |
7 | 2 | 7 | 1 | IP11JS | 62 | 2 | 124 |
8 | 2 | 8 | 2 | IP12JS | 62 | 2 | 124 |
9 | 2 | 9 | 3 | IP119D | 55 | 2 | 110 |
10 | 2 | 10 | 4 | IP129D | 55 | 2 | 110 |
11 | 2 | 11 | 5 | IP11PG | 25 | 2 | 50 |
12 | 2 | 12 | 6 | IP12PG | 25 | 2 | 50 |
SQL Query which is run by me:
SELECT sale_id,
SUM(sold_qyt) AS sold_qyt
FROM sale_items
GROUP BY sale_id
kindly help me with this difficulty thanks in advance
Update: 1-21-2021
i execute new query
SELECT (sma_sale_items.sale_id, sma_categories.code AS sma_products.category_id, sma_products.code AS sma_sale_items.product_code,)
SUM(sold_qyt) AS sold_qyt
SUM(subtotal) AS subtotal
FROM sma_sale_items
LEFT JOIN sma_products ON sma_products.id=sma_sale_items.product_id
LEFT JOIN sma_categories ON sma_categories.code=sma_products.category_id
GROUP BY sma_sale_items.sale_id
ORDER BY sma_categories
but no luck :(
I want the output like this:
Expected OUT PUT:
ID | sale_id | category_name | sold_qyt | subtotal |
1 | 1 | Jelly Sheet | 4 | 248 |
2 | 1 | 9D Glass | 4 | 220 |
3 | 1 | Polished Glass | 4 | 100 |
4 | 2 | Jelly Sheet | 4 | 248 |
5 | 2 | 9D Glass | 4 | 220 |
6 | 2 | Polished Glass | 4 | 100 |
The ID column in your expected result set is very misleading - it appears to be just new ID value for the output result set rather than any of the ID values from the source tables.
If it is important for you then you can use this query:
SELECT ROW_NUMBER() OVER (ORDER BY sale_id, category_id),
sale_id,
category_name,
sold_qty,
subtotal
FROM (
SELECT c.ID as category_id,
si.sale_id,
c.[name] as category_name,
SUM(si.sold_qty) as sold_qty,
SUM(si.subtotal) as subtotal
FROM sale_items si
JOIN product p ON p.ID = si.product_code
JOIN category c ON c.ID = p.category_id
GROUP BY c.ID,
si.sale_id,
c.[name]
) r
If it is not relevant and you only want the sale_id, category_name and the totals then simplify it to:
SELECT si.sale_id,
c.[name] as category_name,
SUM(si.sold_qty) as sold_qty,
SUM(si.subtotal) as subtotal
FROM sale_items si
JOIN product p ON p.ID = si.product_code
JOIN category c ON c.ID = p.category_id
GROUP BY si.sale_id,
c.[name]
ORDER BY sale_id, category_name

Extracting data from table with results from different search

I am trying to extract data from tables with the results from a previous search. I am not really familiar with database query's and have made one that will crash my computer from drawing too much memory.
This data is coming from a board tester and I want certain information.
How many boards were ran during a given period
How many failed
All the failure data for those boards EDIT: This is the one I need to figure out. See Edit at bottom.
The first time a board is ran it creates a record in the Board table
+----------+-------+-----+
| Board_id | Board | rev |
+----------+-------+-----+
| 1 | 1234 | 1 |
| 2 | 1234 | 1 |
| 3 | 1235 | 2 |
| 4 | 5869 | 15 |
+----------+-------+-----+
Each time the board is ran it creates a Test record
+----------+----------+---------+---------------------+
| Test_id | Board_id | Operator| Date_Time |
+----------+----------+---------+---------------------+
| 34 | 1 | 1 | 2017-08-02 09:13:34 |
| 35 | 1 | 1 | 2017-08-02 09:13:36 |
| 36 | 1 | 1 | 2017-08-02 09:13:39 |
| 37 | 2 | 1 | 2017-08-02 09:14:10 |
| 38 | 3 | 1 | 2017-08-02 09:16:24 |
| 39 | 3 | 2 | 2017-08-03 10:40:45 |
| 40 | 4 | 2 | 2017-08-03 10:43:34 |
+----------+----------+---------+---------------------+
...and Results are stored in Results
+-----------+---------+--------+-------------+-------------+
| Result_id | Test_id | Result | Upper_Limit | Lower_Limit |
+-----------+---------+----------------------+-------------+
| 40 | 34 | 2 | 4 | 1 |
| 41 | 34 | 3 | 4 | 1 |
| 42 | 34 | 4 | 4 | 1 |
| 43 | 34 | 0 | 4 | 1 |
| 44 | 35 | 2 | 4 | 1 |
| 45 | 35 | 3 | 4 | 1 |
| 46 | 35 | 4 | 4 | 1 |
| 47 | 35 | 0 | 4 | 1 |
| 48 | 36 | 2 | 4 | 1 |
| 49 | 36 | 3 | 4 | 1 |
| 50 | 36 | 4 | 4 | 1 |
| 51 | 36 | 2 | 4 | 1 |
| 52 | 37 | 2 | 4 | 1 |
| 53 | 37 | 3 | 4 | 1 |
| 54 | 37 | 4 | 4 | 1 |
| 55 | 37 | 2 | 4 | 1 |
| 56 | 38 | 2 | 4 | 1 |
| 57 | 38 | 3 | 4 | 1 |
| 58 | 38 | 4 | 4 | 1 |
| 59 | 38 | 5 | 4 | 1 |
| 60 | 39 | 2 | 4 | 1 |
| 61 | 39 | 3 | 4 | 1 |
| 62 | 39 | 4 | 4 | 1 |
| 63 | 39 | 5 | 4 | 1 |
| 64 | 40 | 2 | 4 | 1 |
| 65 | 40 | 3 | 4 | 1 |
| 66 | 40 | 4 | 4 | 1 |
| 67 | 40 | 3 | 4 | 1 |
+-----------+---------+--------+-------------+-------------+
To get the number of boards, and Board_ID, ran during a given period I query.
SELECT a.Board_ID FROM
Tests a, Results b
WHERE a.Date_Time>='2017-08-02' AND a.Date_Time<'2017-08-03' and
a.Test_ID = b.Test_ID
group by a.Board_ID
To get all associated test to those Board_ID's I query.
SELECT * from
Tests x, (
SELECT a.Board_ID FROM
Tests a, Results b
WHERE a.Date_Time>='2017-08-02' AND a.Date_Time<'2017-08-03' and
a.Test_ID = b.Test_ID
group by a.Board_ID
) y
where x.Board_ID = y.Board_ID
This gives me the correct results, but the query seems off, but when I try to get the failed results from the query above is when I have the most trouble.
SELECT d.Test_ID FROM
Boards a, Tests b, (
SELECT x.Test_ID, x.Board_ID, x.Operator, x.Date_Time from
Tests x, (
SELECT a.Board_ID FROM
Tests a, Results b
WHERE a.Date_Time>='2017-08-02' AND a.Date_Time<'2017-08-03' and
a.Test_ID = b.Test_ID
group by a.Board_ID
) y
)d
WHERE d.Test_ID = b.Test_ID and
b.Result not between Lower_Limit and Upper_Limit
EDIT:
If you look at the Test table I created you will see that board_id 3 got tested twice and on two different days. I need to see the boards that we ran on a given day, this example 2017-08-02, and all associated records to those boards. So since Board_ID #3 was ran on 2 days, and was ran on the day in question, I would need that record included in my query.
My Solution
SELECT * FROM
(
SELECT x.Test_ID, x.Board_ID, x.Operator, x.Date_Time from
Test x, (
SELECT a.Board_ID FROM
Test a
join Results b on a.Test_ID = b.Test_ID
WHERE a.Date_Time>='2017-08-11' AND a.Date_Time<'2017-08-12'
group by a.Board_ID
) y
where x.Board_ID = y.Board_ID
)d
join Boards a on a.Board_ID = d.Board_ID
join Results b on b.Test_ID = d.Test_ID
join Test_Names c on c.Test_Name_ID = b.Test_Name_ID --Table Not shown
WHERE
b.result not between Lower_Limit and Upper_Limit
From this you see I have 3 nested searches into 1. With the 3 individual searches I get all the data I need to parse the information I want. Next will be to find a way to query the database for what I need instead of parsing.
I think you're overthinking this. You don't need all the inline views. Here's how I would write it using ANSI Joins (like #CptMisery suggested in the comments)
SELECT d.test_id, b.board, b.board_rev, r.result_id, r.result -- and whatever else you need.
from tests t
join results r on t.test_id = r.test_id
join boards b on t.board_id = b.board_id
where t.Date_Time>='2017-08-02' AND t.Date_Time<'2017-08-03'
and r.result >Lower_Limit -- or >=
and r.result < Upper_Limit -- or <=, if it can be the limit value
JOIN all the tables based on their relationships (Foreign Key to Primary Key), choose your filters in the where clause, and choose the columns to "project" with Select.
SELECT d.Test_ID FROM
Boards a, Tests b, ( SELECT x.Test_ID,
x.Board_ID,
x.Operator,
x.Date_Time
from Tests x,
(SELECT a.Board_ID
FROM Tests a, Results b
WHERE a.Date_Time>='2017-08-02'
AND a.Date_Time<'2017-08-03'
and a.Test_ID = b.Test_ID
group by a.Board_ID
) y
)d
WHERE d.Test_ID = d.Test_ID
and b.Result >= Lower_Limit
and b. Result <=Upper_Limit

How to write mysql innerquery when get the records count from same table

Query to get results from 2 tables:
SELECT path.* FROM (SELECT tbc.course_name
slp.course_id,slp.student_type,slp.stu_reference_id,
count(slp.course_id) as counttotalWatchedStudents
from tbl_student_learning_path slp LEFT JOIN tbl_courses tbc
on tbc.course_pid = slp.course_id WHERE slp.stu_reference_id =34
and slp.student_type='institute' GROUP BY slp.course_id ) as path
Query result table:
| course_id | totalCollegeStudents | fullwatchedStudentsCount | counttotalWatchedStudents | sumOfWatchPointsForWatchedStudents | totalStudentsAvg | fullwatchedAvg |
|-------------------------------|----------------------|--------------------------|---------------------------|------------------------------------|------------------|----------------|
| Number Systems | 9 | 0 | 3 | 60 | 20.0000 | 0 |
| Percentages | 9 | 0 | 3 | 30 | 10.0000 | 0 |
| Blood Relations | 9 | 3 | 3 | 300 | 100.0000 | 300 |
| Calandar | 9 | 3 | 3 | 300 | 100.0000 | 300 |
| Percentages | 9 | 3 | 3 | 300 | 100.0000 | 300 |
| Permutation & Combination | 9 | 3 | 3 | 300 | 100.0000 | 300 |
| Probability | 9 | 0 | 3 | 90 | 30.0000 | 0 |
| Ratios | 9 | 0 | 3 | 120 | 40.0000 | 0 |
| Time and Work | 9 | 0 | 3 | 150 | 50.0000 | 0 |
| Time Speed & Distance | 9 | 1 | 3 | 140 | 46.6667 | 100 |
| Averages | 9 | 3 | 3 | 300 | 100.0000 | 300 |
| Coding and Decoding | 9 | 3 | 3 | 300 | 100.0000 | 300 |
From the above table, i want to add inner query to the main query
query should be something like this:
( select count(t1.watched_percentage) from tbl_student_learning_path t1
WHERE t1.stu_reference_id =34 and t1.student_type='institute'
AND t1.watched_percentage >= 90 group by t1.course_id )
fullwatchedStudentsCount,
And the result should come like this(this is nothing but if first table counttotalWatchedStudents value is 3 it means that there are 2 type of people
1.students watched full (watched_percentage>=90)
2.students still watching (watched_percentage 1-89)
)
| fullwatchedStudentsCount | fullwatchedStudentsSum |
|--------------------------|------------------------|
| 2 | 200 |
| 1 | 100 |
| 0 | 0 |
| 2 | 200 |
| 1 | 100 |
| 1 | 100 |
| 0 | 0 |
| 2 | 200 |
| 2 | 200 |
| 1 | 100 |
| 2 | 200 |
| 1 | 100 |
If I understand correctly you want sum up the students which saw more than 90% in another column:
I'd do it like this:
SELECT tbc.course_name,
slp.course_id,
slp.student_type,
slp.stu_reference_id,
count(slp.course_id) AS counttotalWatchedStudents,
sum(if(slp.watched_percentage>=90, 1, 0)) AS fullwatchedStudentsCount
sum(if(slp.watched_percentage>=90, watched_percentage, 0)) AS fullwatchedStudentsSum
FROM tbl_student_learning_path slp
LEFT JOIN tbl_courses tbc ON tbc.course_pid = slp.course_id
WHERE slp.stu_reference_id =34
AND slp.student_type='institute'
GROUP BY slp.course_id
enter code here
Hope this helps
So you want to count students with a watched_percentage >= 90? Use conditional aggregation for this:
SELECT
tbc.course_name,
slp.course_id,
slp.student_type,
slp.stu_reference_id,
COUNT(*) as counttotalWatchedStudents,
SUM(slp.watched_percentage >= 90) as fullwatchedStudentsCount,
SUM(slp.watched_percentage < 90) as stillwatchedStudentsCount
FROM tbl_student_learning_path slp
LEFT JOIN tbl_courses tbc ON tbc.course_pid = slp.course_id
WHERE slp.stu_reference_id = 34
AND slp.student_type= 'institute'
GROUP BY slp.course_id;
MySQL treats true = 1 and false = 0, so you can simply sum the trues :-)

SQL statement to combine both fields in one table that match the id element in another table

If you are familiar with Drupal this is using 2 taxonomy terms to describe each content_type_event node. If you don't know Drupal you still have everything below.
I have built a SQL Fiddle that is easier to follow and test with than my drawn out tables. The fiddle has the actual database content which is a little different than the sample info that is shown below but I have tried to make them as similar as possible.
I have three tables:
content_type_event:
____________________________________
| nid | field_eventstartdate_value |
------------------------------------
| 17 | 1984581600 |
| 18 | 1984581600 |
| 19 | 1984581600 |
| 20 | 1984581600 |
| 22 | 1984581600 |
====================================
term_node:
_____________
| nid | tid |
-------------
| 17 | 6 |
| 17 | 15 |
| 18 | 7 |
| 18 | 17 |
| 19 | 6 |
| 19 | 15 |
| 20 | 16 |
| 20 | 9 |
| 22 | 10 |
| 22 | 15 |
=============
term_data:
__________________________
| tid | vid | name |
--------------------------
| 6 | 4 | Location 1 |
| 15 | 3 | Event 1 |
| 7 | 4 | Location 2 |
| 9 | 4 | Location 3 |
| 10 | 4 | Location 4 |
| 16 | 3 | Event 2 |
| 17 | 3 | Event 3 |
==========================
The content_type_event table has information about the event but for the location and event type I have to dig deeper.
The term_node table has all the tid (term id) that goes to each nid (node id). Each nid should have 2 tid for our events. One tid will give us our location the other will give use our event_type.
The term_node table gives the name of the tid and gives us a vid that tells if this name is an event_type or location.
My goal is to get the nid, location, event_type, field_eventstartdate_value for all events. All of the following start in the future so it should look like:
______________________________________________________________
| nid | location | event_type | field_eventstartdate_value |
--------------------------------------------------------------
| 17 | Location 1 | Event 1 | 1984581600 |
| 18 | Location 2 | Event 3 | 1984581600 |
| 19 | Location 1 | Event 1 | 1984581600 |
| 20 | Location 3 | Event 2 | 1984581600 |
| 22 | Location 4 | Event 1 | 1984581600 |
==============================================================
I am not so good with SQL. This is what I have so far:
SELECT event.nid, event.field_eventstartdate_value, location.name, event_type.name
FROM content_type_event AS event
JOIN term_node ON term_node.nid = event.nid
LEFT JOIN (
SELECT tid, name AS location FROM term_data WHERE vid = 4
) AS location ON location.tid = term_node.tid
LEFT JOIN (
SELECT tid, name AS location FROM term_data WHERE vid = 3
) AS event_type ON event_type.tid = term_node.tid;
But this gives me:
______________________________________________________________
| nid | location | event_type | field_eventstartdate_value |
--------------------------------------------------------------
| 17 | NULL | Event 1 | 1984581600 |
| 17 | Location 1 | NULL | 1984581600 |
| 18 | NULL | Event 3 | 1984581600 |
| 18 | Location 2 | NULL | 1984581600 |
| 19 | NULL | Event 1 | 1984581600 |
| 19 | Location 1 | NULL | 1984581600 |
| 20 | NULL | Event 2 | 1984581600 |
| 20 | Location 3 | NULL | 1984581600 |
| 22 | NULL | Event 1 | 1984581600 |
| 22 | Location 4 | NULL | 1984581600 |
==============================================================
I can not seem to group these results together so I get just one full row per event instead of 2 rows containing partial info.
If you want them you can grab the table build statements off of the
FIDDLE: SQL Fiddle.
I think you need this:
SELECT
event.nid,
location.location,
event_type.event_type,
event.field_eventstartdate_value
FROM
content_type_event AS event
LEFT OUTER JOIN (
SELECT
nid,
name AS location
FROM
term_data JOIN
term_node ON term_data.tid=term_node.tid
WHERE term_data.vid = 4) AS location ON location.nid = event.nid
LEFT OUTER JOIN (
SELECT
nid,
name AS event_type
FROM
term_data JOIN
term_node ON term_data.tid = term_node.tid
WHERE term_data.vid = 3) AS event_type ON event_type.nid = event.nid;
http://sqlfiddle.com/#!2/c2459/17/0

MySQL add extra column on result based on another query

I have following Problem
SELECT * from map_user_sticker WHERE map_user_sticker.user_id = 7;
+----+---------+------------+
| id | user_id | sticker_id |
+----+---------+------------+
| 35 | 7 | 55 |
| 3 | 7 | 30 |
| 32 | 7 | 49 |
| 33 | 7 | 52 |
| 34 | 7 | 43 |
| 36 | 7 | 50 |
+----+---------+------------+
6 rows in set (0.00 sec)
SELECT * FROM sticker;
+----+--------------------------------------------------+
| id | word |
+----+--------------------------------------------------+
| 40 | I love Sonal |
| 41 | Add User to Database |
| 39 | This is a dream Project |
| 33 | Narendra Sisodiya |
| 34 | Sourabh Parmar |
| 30 | Sonal Sisodiya |
| 42 | I love India |
| 43 | I love Linux |
| 44 | I hate Congress |
| 45 | I love jQuery |
| 48 | Modi will be the PM |
| 47 | Ramdev Baba is my Super Hero |
| 49 | हिन्दी से प्यार है |
| 50 | Linux is better then Windows |
| 52 | I am from Sehore |
| 55 | I have 2 little kids - sadu and sonu |
+----+--------------------------------------------------+
16 rows in set (0.00 sec)
I basically want to generate Result like
+----+--------------------------------------------------+----------+
| id | word | present |
+----+--------------------------------------------------+----------+
| 40 | I love Sonal | 0 |
| 41 | Add User to Database | 0 |
| 39 | This is a dream Project | 0 |
| 33 | Narendra Sisodiya | 0 |
| 34 | Sourabh Parmar | 0 |
| 30 | Sonal Sisodiya | 1 |
| 42 | I love India | 0 |
| 43 | I love Linux | 1 |
| 44 | I hate Congress | 0 |
| 45 | I love jQuery | 0 |
| 48 | Modi will be the PM | 0 |
| 47 | Ramdev Baba is my Super Hero | 0 |
| 49 | हिन्दी से प्यार है | 1 |
| 50 | Linux is better then Windows | 1 |
| 52 | I am from Sehore | 1 |
| 55 | I have 2 little kids - sadu and sonu | 1 |
+----+--------------------------------------------------+----------+
16 rows in set (0.00 sec)
Please Help me !!
I want to generate a extra column called "present", based on following condition
If sticker_id from query1 == id from query 2 then present = 1
else present = 0
Here the Answer I was wanted to get !
Answer 1 -
SELECT s.* , IF(FIND_IN_SET(7,(GROUP_CONCAT(m.user_id))) != 0 , 1,0) as present, COUNT(m.user_id) as totalUsers
FROM sticker s
LEFT JOIN map_user_sticker m
ON s.id = m.sticker_id
GROUP BY id;
Answer 2 -
SELECT id,word, (case when 7 in (select user_id from map_user_sticker WHERE map_user_sticker.sticker_id=sticker.id) then 1 else 0 end) as present
from sticker;
I don,t know which one is fast and better
Try this:
select id,word,
case(when id in (select sticker_id from map_user_sticker) then 1 else 0 end)
as present from sticker;
Hope, this will help:
SELECT sticker.id, sticker.word, (IF(sticker_id IS NULL, 0, 1)) AS present FROM sticker LEFT JOIN map_user_sticker ON (sticker.id = map_user_sticker.sticker_id)
Try this query -
SELECT s.*, IF(COUNT(m.sticker_id) > 0, 1, 0) present FROM sticker s
LEFT JOIN map_user_sticker m
ON s.id = m.sticker_id
GROUP BY
s.id;
Is this what you want?
SELECT s.*, IF(m.sticker_id IS NULL, 0, 1) present FROM sticker s
LEFT JOIN map_user_sticker m
ON s.id = m.sticker_id
WHERE m.user_id = 7;