I have 3 MYSQL Tables User table and 2 Transactions table.
My User table is as follows.
id inviter_id active .... (other columns)
2 1 1
3 1 1
4 2 1
5 1 1
6 2 1
My txn1 table is
id payer_id receiver_id amount type
1 2 1 20 profit
2 3 1 30 profit
3 4 2 20 profit
4 3 2 50 profit
5 5 2 20 profit
My txn2 table is
id payer_id receiver_id amount txn_type
1 2 1 20 profit
2 3 2 30 profit
3 4 2 20 profit
4 3 1 50 profit
5 5 1 20 profit
What I need to get is,
Consider I'm querying for the user 2. I need the profit he has earned from each of his downline or referrals using the inviter_id column.
For example, If I want to get the profit of User #2 from Txn1 and Txn2 table, it should get the txns made by user 4 and user 6 in txn1 and txn2 tables.
What I have tried so far is,
$userID = 2;
$this->db->select('u.id as partner_id, SUM(txn1_profit.amount) AS t1Profit, SUM(txn2_profit.amount) AS t2Profit');
$this->db->from('users u');
$this->db->join('txn1 txn1_profit', "u.id = txn1_profit.payer_id AND $userID = txn1_profit.receiver_id AND 'profit' = txn1_profit.txn_type",'LEFT');
$this->db->join('txn2 txn2_profit', "u.id = txn2_profit.payer_id AND $userID = txn2_profit.receiver_id AND 'profit' = txn2_profit.txn_type",'LEFT');
$this->db->where('u.inviter_id', $userID);
$this->db->group_by('u.id');
$query = $this->db->get();
$row = $query->result();
if (empty($row))
return FALSE;
return $row;
The problem with this query is i'm getting a huge sum value.
If schema of your transaction tables is same then I would suggest you to change your schema and have one single transaction table to store such information. By changing your current design will help you to build simple queries may reduce no. of joins.
For your current schema I can think of 2 possible ways to address your profit value issue.
Calculate sum from your transaction tables in sub-clause and then do a join with users table
select u.inviter_id,
sum(t1.t1Profit),
sum(t2.t2Profit),
sum(t1.t1Profit) + sum(t2.t2Profit) total
from users u
left join (
select payer_id, sum(amount) t1Profit
from tx1
where 2 = receiver_id
and 'profit' = type
group by payer_id
) t1 on u.id = t1.payer_id
left join (
select payer_id, sum(amount) t2Profit
from tx2
where 2 = receiver_id
and 'profit' = txn_type
group by payer_id
) t2 on u.id = t2.payer_id
where u.inviter_id = 2;
Or combine data of your transaction tables using union all and then do a join with users table
select u.inviter_id,
sum(t1.amount) total
from users u
left join (
select payer_id, amount
from tx1
where 2 = receiver_id
and 'profit' = type
union all
select payer_id, amount
from tx2
where 2 = receiver_id
and 'profit' = txn_type
) t1 on u.id = t1.payer_id
where u.inviter_id = 2;
DEMO
Related
Hello Developers/Programmers
I am working on withdrawal function on my website.
So it goes like this
I need to total the 3 tables i have by User ID with status of '1' ,and Subtract the Inputed amount by the User Requested the Withdrawal
These are my 3 tables
tbl_bonus_1
id | amount | user_id | status
1 20 1 1
2 20 1 1
3 20 3 1
tbl_bonus_2
id | amount | user_id | status
1 30 1 1
2 30 1 1
3 30 3 1
tbl_bonus_3
id | amount | user_id | status
1 40 1 1
2 40 1 1
3 40 3 1
Now I need to get all that 3 tables by USER ID and get the total of it.
After getting the total i need to subtract the Inputted quantity of the USER
and update the status to 0 so that the user cant withdraw again.
Im using Codeigniter 3.1.5
select user_id, sum(amount)
from
(select * from tbl_bonus_1
union
select * from tbl_bonus_2
union
select * from tbl_bonus_3) tt
where status = 1
group by user_id
DEMO:
http://sqlfiddle.com/#!9/7f1807e/1
And UPDATE (single user):
UPDATE tbl_bonus_1 t1 INNER JOIN tbl_bonus_2 t2
ON t1.user_id = t2.user_id
INNER JOIN tbl_bonus_3 t3
ON t1.user_id = t3.user_id
SET t1.amount = 0, t2.amount = 0, t3.amount = 0
WHERE t1.user_id = 1;
Realistically, you don't want to subtract from these tables if you want to manage a balance. You need to add a 4th table that is withdrawal amount, so you can capture the transactions. If you have a total of 160 across 3 tables, and the user withdrawals 150, how would you determine which to decrement.
I would suggest actually consolidating all of these into 1 trasaction table, and capture the amounts there.
So to get what you need you will need to leverage variables which will need to be passed to the query. Below will give you what you are asking for. That being said, this is not the correct way to do this. Also, there is no way to determine which of the 3 balances you want to subtract the withdraw from. This is just not how transaction ledgers work and for a lot of reasons I am not going to get in to right now. At the bottom of this answer is how I suggest you should build your table. You will be able to get information with more easy while capturing more/better data.
How to get data from current structure:
set #withdraw = 150.00, #user = 1;
select user_id, sum(amount) as prevBalance
, #remainingBalance := if(#user = user_id,sum(amount)-#withdraw,sum(amount)) as remainingBalance
from
(select * from tbl_bonus_1
union
select * from tbl_bonus_2
union
select * from tbl_bonus_3) balance
group by user_id;
How you should build your schema:
CREATE TABLE ledger (id int NOT NULL AUTO_INCREMENT
,user_id int
, amount decimal(5,2)
, transaction_type varchar(20)
,PRIMARY KEY (ID));
INSERT INTO ledger VALUES
(null,1,20,'Bonus1'),
(null,1,20,'Bonus1'),
(null,3,20,'Bonus1'),
(null,1,30,'Bonus2'),
(null,1,30,'Bonus2'),
(null,3,30,'Bonus2'),
(null,1,40,'Bonus3'),
(null,1,40,'Bonus3'),
(null,3,40,'Bonus3'),
(null,1,-150,'Withdraw')
;
Then all you would need to do is run the following query.
select user_id, sum(amount) balance from ledger
group by user_id;
Q : I am trouble to do following task in mysql query.
Task is get all products (If product is duplicate than sum of it's qty) and deduct wastage stock (If wastage product is duplicate than sum of it's qty).
I have two tables like,
1) manage_stock
2) manage_wastage
manage_stock
=> This table has p_id(Product ID) and many rows with product duplication's.
p_id p_name p_qty
1 Pro-1 10
2 Pro-2 15
3 Pro-3 8
1 Pro-1 15
manage_wastage
=> This table has p_id(Product ID) of manage_stock table. It is also many rows with product duplication's.
p_id w_qty
1 2
1 4
3 5
Desired Output
p_id p_name p_qty w_qty final_qty
1 Pro-1 20 6 14
2 Pro-2 15 0 15
3 Pro-3 8 5 3
Thank you very much.
You just have to compute the difference between the stock quantity and the wastage
SELECT s.p_id, s.p_name, SUM(p_qty), SUM(w_qty), SUM(p_qty) - SUM(w_qty) as final_qty
FROM manage_stock s
LEFT OUTER JOIN manage_wastage w
ON s.p_id = w.p_id
GROUP BY s.p_id, s.p_name
try this one
SELECT s.p_id, s.p_name, SUM(p_qty),SUM(ifnull(w_qty, 0)),SUM(p_qty - ifnull(w_qty, 0)) as total
FROM manage_stock s
left outer JOIN manage_wastage w
ON s.p_id = w.p_id
GROUP BY s.p_name
its work
SELECT ms.p_id ,GROUP_CONCAT(ms.p_name)p_name ,SUM(ms.p_qty) p_qty ,SUM(mw.w_qty) w_qty,SUM(ms.p_qty)-SUM(mw.w_qty) final_qty FROM manage_stock ms
INNER JOIN manage_wastage mw on ms.p_id =mw.p_id
GROUP BY ms.p_id
Try above code.
As p_name always unique with p_id GROUP_CONCAT() only returns single name.
I'm making a customer database application for a dancing school.
I need to display an overview of all customers that are participating in the same dancing level. But I want the overview order by couples not by the customer ID.
For this I'm joining three tables (look at the query below)
Each customer has a unique ID in the tabel CRM_CONTACTS and also has in it's row a reference to his or her partner (PARTNER_ID).
Table CRM_CONTACTS
ID CONTACTS_LNAME
1 VON KLOMPENBURG
2 Mc Donalds
3 MC Adams
4 Mr X
Then I have CRM_PRODUCTS
ID PRODUCTS_NAME
1 Beginners
2 intermediate
3 advanced
Then the table in which I assign a product/level to a contact and also indicate his/her partner
ID CONTACTS_ID PRODUCTS_ID PARTNER_ID
1 1 1 4
2 2 1 3
3 3 1 2
4 4 1 1
Now I would like to receive a list order by couple based on the parter_id
So for the beginners level I would get a list like this
1 VON KLOMPENBURG
2 Mr X
3 Mc Donalds
4 Mc Adams
Here's my select statement
$result = mysqli_query($coni,"SELECT CRM_PRODUCTS_PURCHASE.ID, CONTACTS_ID,
CRM_PRODUCTS.PRODUCTS_NAME,
CRM_PRODUCTS.PRODUCTS_PRICE,CRM_PRODUCTS_PURCHASE.PARTNER_ID,
CRM_PRODUCTS_PURCHASE.PARTNER_NAME,
PRODUCTS_PURCHASE_REMARKS,PRODUCTS_PURCHASE_DISCOUNT,
PRODUCTS_PURCHASE_PAIDBYBANK,PRODUCTS_PURCHASE_PAIDBYCASH,
CRM_CONTACTS.CONTACTS_LNAME, CRM_CONTACTS.CONTACTS_FNAME
FROM CRM_PRODUCTS_PURCHASE
LEFT JOIN CRM_CONTACTS ON CRM_PRODUCTS_PURCHASE.CONTACTS_ID = CRM_CONTACTS.ID
LEFT JOIN CRM_PRODUCTS ON CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = CRM_PRODUCTS.ID
WHERE CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = '". $PRODUCTS_ID . "'");
You can do something like this:
$result = mysqli_query($coni,"SELECT CRM_PRODUCTS_PURCHASE.ID, CONTACTS_ID,
CRM_PRODUCTS.PRODUCTS_NAME,
CRM_PRODUCTS.PRODUCTS_PRICE,CRM_PRODUCTS_PURCHASE.PARTNER_ID,
CRM_PRODUCTS_PURCHASE.PARTNER_NAME,
PRODUCTS_PURCHASE_REMARKS,PRODUCTS_PURCHASE_DISCOUNT,
PRODUCTS_PURCHASE_PAIDBYBANK,PRODUCTS_PURCHASE_PAIDBYCASH,
CRM_CONTACTS.CONTACTS_LNAME, CRM_CONTACTS.CONTACTS_FNAME
FROM CRM_PRODUCTS_PURCHASE
LEFT JOIN CRM_CONTACTS ON CRM_PRODUCTS_PURCHASE.CONTACTS_ID = CRM_CONTACTS.ID
LEFT JOIN CRM_PRODUCTS ON CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = CRM_PRODUCTS.ID
WHERE CRM_PRODUCTS_PURCHASE.PRODUCTS_ID = '". $PRODUCTS_ID . "'
ORDER BY IF (ID < PARTNER_ID, ID, PARTNER_ID)");
And your customers will be ordered in couples.
Im having some trouble with this.
Here's an example of my tables.
Booking
id zone_id name excursion_id
1 2 1
2 1 1
3 2 1
The table where I have the quantities
booking_price
id_booking id_price quantity
1 1 2
1 2 3
2 1 1
2 2 0
3 1 2
3 2 3
Here the zone table
Zone
id Name
1 a
2 b
3 c
So I want to have a table like that
Zone_id Quantity
1 1
2 10
3 0
The problem is when im joining tables and filtering by excursion_id im not getting ALL the zones.
I want to know how many people goes in each zone.
I think better way of doing it is
select z.id, coalesce(sum(bp.quantity),0) as quantity
from Booking b
right join Zone z on z.id = b.zone_id AND b.excursion_id = 1
left join booking_price bp on bp.id_booking = b.id
group by z.id
demo http://sqlfiddle.com/#!2/771f5/13
You could use a query like:
SELECT zone.id as zone_id,
sum(quantity) as Quantity
FROM zone
LEFT JOIN Booking on Booking.zone_id = zone.id
LEFT JOIN Excursion on Excursion.id_booking = Booking.id
GROUP BY zone.id
I have this table:
This selection is is duplicated many times for different var_lines (which pretty much work as one row of data, or respondent for a survey) and set_codes (different survey codes).
With this query:
SELECT
*, COUNT(*) AS total
FROM
`data`
WHERE
`var_name` = 'GND.NEWS.INT'
AND(
`set_code` = 'BAN11A-GND'
OR `set_code` = 'BAN09A-GND'
OR `set_code` = 'ALG11A-GND'
)
AND `country_id` = '5'
GROUP BY
`data_content`,
`set_code`
ORDER BY
`set_code`,
`data_content`
The query basically counts the number of answers for a specific question. Then groups them survey (set_code).
What I need is for each of the grouped data_content answers for GND.NEWS.INT to also show the SUM of all the corresponding GND_WT with the same var_line.
For example if I had this:
data_id data_content var_name var_line
1 2 GND.NEW.INT 1
2 1.4 GND_WT 1
3 2 GND.NEW.INT 2
4 1.6 GND_WT 2
5 3 GND.NEW.INT 3
6 0.6 GND_WT 3
I would get something like this:
data_id data_content var_name var_line total weight
1 2 GND.NEW.INT 1 2 3
5 3 GND.NEW.INT 3 1 0.6
Thanks for any help.
Your requirements are not exactly clear, but I think the following gives you what you want:
select d1.data_id,
d1.data_content,
d1.var_name,
d1.var_line,
t.total,
w.weight
from data d1
inner join
(
select data_content,
count(data_content) Total
from data
group by data_content
) t
on d1.data_content = t.data_content
inner join
(
select var_line,
sum(case when var_name = 'GND_WT' then data_content end) weight
from data
group by var_line
) w
on d1.var_line = w.var_line
where d1.var_name = 'GND.NEW.INT'
See SQL Fiddle with Demo
This Query can be suitable for your specific example:
select st.data_id,
st.data_content,
st.var_name,
st.var_line,
count(st.data_id) as total,
sum(st1.data_content) as weight
from data st
left join data st1 on st1.var_name = 'GND_WT' AND st1.var_line=st.var_line
where st.var_name='GND.NEW.INT'
group by st.data_content
Regards,
Luis.