mysql calculation data in two table - mysql

I want to calculate commisions according to product commision type and its commision ratio for each sales (cash). One product has more one commision type. For example, Seller Commision, Manager Commision, Branch Commision etc.
I want to give a report sales and their commision in list.
Product - Sale Price(Cash) - Seller Commision - Manager Commision - Branch Commision
Computer / 1000 / 1000 * 0.3 / 1000 * 0.2 / 1000 * 0.4
I have two tables; first one is sale_table which has columns;
sale_id, shop_id, product_id, cash
ex: (3,5,11,100)
second one is product_commision_table which has columns;
**product_commision_id, shop_id, product_id, commision_type_id, commision **
(1819, 5, 11, 9, 32),
(1820, 5, 11, 2, 0.3),
(1821, 5, 11, 7, 1),
(1822, 5, 11, 5, 0.5),
(1823, 5, 11, 6, 0.7)
I want to calculate commisions according to cash and result should seem like:
100*32 , 100*0.3, 100*1, 100*0.5, 100*0,7
How can I do, what should be query in mysql ?

SELECT s.*, c.*, s.cash * c.commission as commission_total FROM sales_table as s, product_commissions_table as c WHERE s.product_id = c.product_id
Shortcut version of INNER JOIN posted by another user.

Related

Count consecutive rows in mySQL 5.6

I'm trying to figure out counting the consecutive values row after row.
I have a mySQL / php website.
Based on Racing league results table, I have such example data:
(race id, season number, track number, first (p1), second (p2).... last (p2) filled with pilot ID).
id, season, track, p1, p2.... p20
1, 1, 1, 1, 4, .... 15
2, 1, 2, 3, 5, .... 15
3, 1, 3, 1, 4, .... 15
4, 1, 4, 1, 2, .... 15
5, 1, 5, 1, 4, .... 15
6, 1, 6, 2, 2, .... 15
7, 1, 7, 2, 4, .... 15
8, 1, 8, 1, 2, .... 15
As you can see, pilotID n.1 won 3 times consecutively, from race 3 to race 5, while pilotID n.2 won 2 times consecutively, from race 6 to race 7.
My goal output table would be:
count, pilot, fromRaceID, toRaceID
3, 1, 3, 5
2, 2, 6, 7
ordered by count.
I know it is complicated, and even mightn't be possible; I found major difficulties trying to do so, therefore your help would be extremely appreciated.
This is a type of gaps-and-islands. Subtract a sequence number and the "adjacent" values will be constant:
select p1, min(trackid), max(trackid), count(*)
from (select t.*,
row_number() over (partition by p1 order by track_number) as seqnum
from t
) t
group by p1, (track_number - seqnum)
having count(*) > 1;
EDIT:
In older versions of MySQL, you can use:
select p1, min(trackid), max(trackid), count(*)
from (select t.*,
(select count(*)
from t t2
where t2.p1 = t.p1 and t2.track_number <= t.track_number
) as seqnum
from t
) t
group by p1, (track_number - seqnum)
having count(*) > 1;

SQL (MySQL) Count average attributable to a one person for each class

Hello there. I would ask for help with my problem. I have a modeling situation like this: I have two tables:
STUDENTS
ID, FIRST_NAME, LAST_NAME,DATE_OF_BIRTH, CLASS,
1, Petr, Fish, 4.3.1984, 4A
2, John, Stone, 5.5.1990, 4A
3, Jack, Clark, 6.3.1983, 4A
4, George, Field, 5.8.1955, 4A
5, John, Rock, 6.1.1999, 4B
6, Patrick, Light, 1.11.1983, 4B
and
POINTS_MATH:
STUDENT_ID, POINTS
1, 15
1, 20
2, 30
3, 11
3, 5
4, 3
And I need to count average of points attributable to one student in each class (also with null value), so the result may look like this:
CLASS, AVERAGE_POINTS
4A, 21
4B, 0
Thanks a lot for every answer
Based on your example you don't want the average points, but the sum of all points divided by the number of students:
SELECT a.CLASS,
COALESCE(SUM(p.POINTS) / COUNT(DISTINCT p.STUDENT_ID), 0)
FROM STUDENTS AS s
LEFT JOIN POINTS_MATH AS p ON s.ID = p.STUDENT_ID
GROUP BY c.CLASS
You might also check if the average of the average per student better fits your need:
SELECT s.CLASS, COALESCE(AVG(avgPoints), 0)
FROM STUDENTS AS s
LEFT JOIN
(
SELECT STUDENT_ID, AVG(POINTS) AS avgPoints
FROM POINTS_MATH
GROUP BY STUDENT_ID
) AS p
ON s.ID = p.STUDENT_ID
GROUP BY s.CLASS

select: result based on occurrence of explicit value

Given is following mysql table:
CREATE TABLE fonts
(`id` int, `fontName` varchar(22), `price` int,`reducedPrice` int,`weight` int)
;
INSERT INTO fonts
(`id`, `fontName`, `price`,`reducedprice`,`weight`)
VALUES
(1, 'regular', 50,30,1),
(2, 'regular-italic', 50,20,1),
(3, 'medium', 60,30,2),
(4, 'medium-italic', 50,30,2),
(5, 'bold', 50,30,3),
(6, 'bold-italic', 50,30,3),
(7, 'bold-condensed', 50,30,3),
(8, 'super', 50,30,4)
;
As an example a user chooses following ids: 1,2,3,5,6,7
which would result in following query/result:
> select * from fonts where id in(1,2,3,5,6,7);
id fontName price reducedPrice weight
1 regular 50 30 1
2 regular-italic 50 20 1
3 medium 60 30 2
5 bold 50 30 3
6 bold-italic 50 30 3
7 bold-condensed 50 30 3
Is it possible to have a kind of "if statement" in a query to return a new field based on column weight. Where a value occurs more than once reducedPrice should be returned as newPrice else price:
id fontName price reducedPrice weight newPrice
1 regular 50 30 1 30
2 regular-italic 50 20 1 20
3 medium 60 30 2 60
5 bold 50 30 3 30
6 bold-italic 50 30 3 30
7 bold-condensed 50 30 3 30
Which means ids 1,2,5,6,7 should be reduced but id 3 not as its weight "2" only occurs once
Please find a fiddle here: http://sqlfiddle.com/#!9/73f5db/1
And thanks for your help!
Write a subquery that gets the number of occurrences of each weight, and join with this. Then you can test the number of occurrences to decide which field to put in NewPrice.
SELECT f.*, IF(weight_count = 1, Price, ReducedPrice) AS NewPrice
FROM fonts AS f
JOIN (SELECT weight, COUNT(*) AS weight_count
FROM fonts
WHERE id IN (1, 2, 3, 5, 6, 7)
GROUP BY weight) AS w ON f.weight = w.weight
WHERE id IN (1, 2, 3, 5, 6, 7)
Updated fiddle
select *,if(occurences>=2,reducedPrice,price) as newPrice from fonts
left join (Select count(id) as occurences, id,weight from fonts
where fonts.id in(1,2,3,5,6,7) group by weight) t on t.weight = fonts.weight
where fonts.id in(1,2,3,5,6,7);
The mysql if keyword reference is here:https://dev.mysql.com/doc/refman/5.1/en/control-flow-functions.html#function_if
Edit: Added fiddle, changed to instances as comment requested.
Updated fiddle:http://sqlfiddle.com/#!9/a93ef/14
SELECT DISTINCT x.*
, CASE WHEN y.weight = x.weight THEN x.reducedPrice ELSE x.price END newPrice
FROM fonts x
LEFT
JOIN
( SELECT * FROM fonts WHERE id IN(1,2,3,5,6,7) )y
ON y.weight = x.weight
AND y.id <> x.id
WHERE x.id IN(1,2,3,5,6,7)
ORDER
BY id;

How to join three tables to get Sum

I have three tables: Products, Purchase, Invoice
Product table:
Producct_no Name
1 A
2 B
3 C
Purchase table:
Purchase_no Product_no Qty
001 1 81
002 2 150
003 3 10
Invoice table:
Invoice_no Product_no Qty
001 1 20
002 2 10
003 3 10
I want to get each product's purchase quantity and invoice quantity, I used following query
SELECT PR.product_no, sum(P.qty),sum(I.qty)
FROM products PR
LEFT JOIN invoice I ON I.product_no=PR.product_no
LEFT JOIN purchase P ON P.product_no=PR.product_no
group by PR.product_no
product_no sum(P.qty) sum(I.qty)
001 162 160
002 150 50
003 10 10
EDIT: Expected results
product_no sum(P.qty) sum(I.qty)
001 81 20
002 150 10
003 10 10
My query is giving me wrong response (sum of quantities are wrong), please help me to correct my query to get the results properly. thanks
I don't think your sample data is really what you have based on the information provided. My best guess here is that your query is doing a fan-out on either or both of those joins which is messing up your sums. You need to sum them separately, else additional rows in either on of those joins will fan out the other join, duplicating your results in the sum. This is evident in your result since 001 looks to be double (even though your sample data doesn't show it).
Something like this would ensure sums independent of each other:
SELECT PR.product_no,
( SELECT sum(I.qty)
FROM invoice I
WHERE I.product_no=PR.product_no ) invoice_qty,
( SELECT sum(P.qty)
FROM purchase P
WHERE P.product_no=PR.product_no ) purchase_qty
FROM products PR
I think you have a problem with GROUP BY there. I would do something like this in this case
SELECT P.Product_no, Inv.InvProdSum, Pur.PurProdSum
FROM Product P
LEFT JOIN (SELECT Product_no, SUM(Qty) AS InvProdSum
FROM Invoice
GROUP BY Product_no) AS Inv
ON P.Product_no = Inv.Product_no
LEFT JOIN (SELECT Product_no, SUM(Qty) AS PurProdSum
FROM Purchase
GROUP BY Product_no) AS Pur
ON P.Product_no = Pur.Product_no
Here is SQL FIddle for that http://sqlfiddle.com/#!9/731a5/1
NOTE i add some extra value here to test how it's work...
GL!
Here is my solution without subqueries:
with
product(product_no, name) as (values
(1, 'A'),
(2, 'B'),
(3, 'C')
),
purchase(purchase_no, product_no, qty) as (values
('001', 1, 81),
('002', 2, 150),
('003', 3, 10),
('004', 1, 1000)
),
invoice(invoice_no, product_no, qty) as (values
('001', 1, 20),
('002', 2, 10),
('003', 3, 10),
('004', 2, 5000)
),
mixed as
(select d.product_no,
purchase_no, p.qty as qty_purchase,
invoice_no, i.qty as qty_invoice,
row_number() over(partition by purchase_no) as rn_purchase,
row_number() over(partition by invoice_no) as rn_invoice
from product d
left join purchase p on p.product_no = d.product_no
left join invoice i on i.product_no = d.product_no
)
select product_no,
sum((case when rn_purchase = 1 then 1 else 0 end) * qty_purchase) as sum_purchase,
sum((case when rn_invoice = 1 then 1 else 0 end) * qty_invoice) as sum_invoice
from mixed
group by product_no
order by product_no
;
And results:
product_no|sum_purchase|sum_invoice|
----------|------------|-----------|
1| 1081| 20|
2| 150| 5010|
3| 10| 10|

mysql join result if only have all features

I have a checkbox with all features. A users select some features.
How can I do to list all persons with all the features selected.
person
- id
- name
features
- id
- name
person_feature
- person_fk
- feature_fk
For example only the persons that have features 1,5 and 9
Not persons with feature 1 and person with feature 5... only with this features at the same time
Confirm... Exclusively what provided, or a MINIMUM OF. Ex: if user wants features 1, 5, 9 but some people have
(1, 2, 5, 8, 9),
(1, 5, 6, 7, 9),
(1, 5, 9, 12)...
these would all be considered ok as they have the MINIMUM of the 1, 5 and 9 that you are looking for.
select
pf.person_fk,
p.name
from
person_feature pf
join person p
on pf.person_fk = p.id
group by
pf.person_fk,
p.name
having
sum( case when pf.feature_fk in ( 1, 5, 9 ) then 1 else 0 end ) >= 3
If you ONLY want those with exactly 3, just change >= to just =