Using SQL to work out % of times a specific event occurrs - mysql

Hopefully you can help me, typically I do analysis in R and basic querying in SQL and have tripped myself up over what seems like a basic problem.
I have a basic table: table
ID product % discount (int)
1 a 10
2 a 0
3 a 5
4 b 0
5 b 5
6 b 5
7 c 0
I want to calculate the % of times a discount if applied by product. I have tried a number of approaches all either show incorrect values or error and I am unsure if it's syntax or approach driven.
Examples of erroneous code below, although please let me know if there is an easier way.
I want to calculate the % of times a discount if applied by product. I have tried a number of approaches all either show incorrect values or error and I am unsure if it's syntax or approach driven.
SELECT count(discount) as discountN where discount > 0,
count(discountN) * 100.0 / (select count(product_id) from table) as percent
FROM table
group by ID
with total as select count(*) as total from table
select count(discount) / total
WHERE discount > 0
FROM table
group by ID
I am expecting:
a: 66%
b: 66%
c: 0%

You can try below using case when
SELECT product,
(count(case when discount > 0 then discount end) * 100.0) / count(product_id) as percent
FROM table
group by product

If you want the ratio with discounts greater than 0, then I recommend avg():
SELECT product,
AVG(CASE WHEN discount > 0 THEN 1.0 ELSE 0 END) as ratio
FROM table
GROUP BY product;
If you want values from 0 to 100 rather than 0 to 1, then use 100.0 rather than 1.0.
In MySQL, this can be simplified to:
SELECT product,
AVG( discount > 0 ) as ratio
FROM table
GROUP BY product;

Related

MULTIPLY EACH ROW VALUES WITH DIFFERENT VALUES

Hello everyone,
Here I am trying to do the multiplication of reach row multiplied by different values.
For example..,
I have 3 columns with customer_id(int), product_name(varchar) , price(int)
Now, In the column of Product_name = LV, MK, Price column should be multiplied by 10 (Price * 10) and Product_name = YSL product Price column should be multiplied by 20 (Price * 20). Display the results as a new columns as points achieved by each customer.
Could you please tell me how can I achieve this..,
Your help could be appreciated
You can get it done by incorporating a CASE statement directly in the SQL.
SELECT
customer_id,
product_name,
CASE
WHEN product_name IN ('LV', 'MK') THEN price * 10
WHEN product_name = 'YSL' THEN price * 20
ELSE price
END as adjusted_price
FROM TABLENAME;

How to implement score points for each WHERE clause in SELECT statement

how can i create column with information about how much condition was passed for each field?
eg. I have client who find property with max price to 500000, 3th floor and living area between 45 meters. Now when i use "AND" for each condidtions i will get rows with 100% compatibility. But What abaout to find rows with the same condidtions as before but without living area in range. There will be 66% copatibility because 2/3 of my conditions is passed.
There is my sqlfiddle http://sqlfiddle.com/#!9/1ef60c/5
Simple way to solve your problem is:
SELECT *,
(
CASE WHEN `property_max-price` < 550000 THEN 1 ELSE 0 END
+
CASE WHEN property_additional LIKE "%hot_water%" THEN 1 ELSE 0 END
+
CASE WHEN `property_floor-from` >= 2 AND `property_floor-to` <=5 THEN 1 ELSE 0 END
) / 3 * 100 AS `%`
FROM client

mySQL Sum Production_Needed Group BY Part_ID

Want to generate a result of Open orders where Production is needed. At issue is each part may have more than one open order. With the GROUP BY my code gives me only one order but does give me the total Production_Needed (which is also a negative in value for orders with enough inventory).
Does my SUM(...) as Production_Needed need to be in the WHERE ?
Thanks,
SELECT part.part_ID AS Part_Part_ID,
part.Inventory, part.part_number,
ord.part_id AS Order_Part_ID,
ord.order_type, ord.quantity_ordered, ord.quantity_shipped,
SUM(ord.quantity_ordered - ord.quantity_shipped - part.Inventory) AS Production_Needed
FROM production_orders ord
JOIN production_part part ON ord.part_ID = part.part_ID
WHERE ord.is_Active = True AND ord.order_type = 0
GROUP BY Order_Part_ID
ORDER BY part.part_number ASC
Data Production_Part part
Part_ID
Part_Inventory
Part_Number
1
12500
97-528
2
0
FC2569
3
1000
39367
Data Production_Orders Ord
Order_Part_ID
Order_Type
Quantity_Ordered
Quantity_Shipped
1
0
8000
0
2
0
1000
500
2
0
1000
0
3
1
10
0
Desired Result - Only Parts that need production
Part_ID
Quantity_Ordered
Quantity_Shipped
2
1000
500
2
1000
0
Untested: need a sampled data set and structure for testing:
This creates an inline view and totals the inventory order amounts then stubtracts it from the inventory to determine if there is a production needed to fulfil open orders. I'd have to use some additional analytical functions if we needed to do this on an order by order basis however; or join these results back into the orders...
--Show parts which lack inventory to fullfill outstanding open orders.
SELECT
P.Part_ID as Part_Part_ID
, P.Inventory
, P.Part_Number
, O.Part_ID as Order_Part_ID
, UnDel_Units-coalesce(P.Inventory,0) as Production_Needed --use coalesce incase no part record exists for some reason.
FROM Production_Part P
RIGHT JOIN ( --use right join just incase part record doesn't exist for some reason
SELECT part_ID, SUM(quantity_ordered-quantity_shipped) as UnDel_Units
FROM PRODUCTION_ORDERS
WHERE IS_ACTIVE=TRUE
and ORDER_TYPE=0
GROUP BY PART_ID) O --derived table "O" for orders showing sum ottal by part of units undelivered
on O.Part_ID=P.Part_ID
WHERE UnDel_Units > coalesce(P.Inventory,0)
-- If inventory is > undelivered units for the part, ignore as additional production isn't needed

I need to create a query with a dynamic range of value in mysql

I have a table with a column called "Points", the value of this column have a min value of 0, and a max value of 100.000. I have to do an analysis per range of this column, so I wrote a query like this:
select case when Points between 0 and 5000 then '0 - 5000'
when Points between 5001 and 20000 then '50001 - 20000'
when Points > 20000 then '> 20000'
else 0 end RangeP
from Sales
The problem is that the customer wants to see for each 2.000 points from 0 to 100.000
If I wrote the query using the case, the query will get really big, so I'd like one way to get dynamically this range.
It is possible? Thank you very much
You may create a table which contains the ranges, and their text labels, and then join to it, e.g.
SELECT
s.Points,
COALESCE(r.label, 'range not found') AS range
FROM Sales s
LEFT JOIN
(
SELECT 0 AS start, 2000 AS end, '0 - 2000' AS label UNION ALL
SELECT 2001, 4000, '2001 - 4000' UNION ALL
...
SELECT 98000, 100000, '98000 - 100000'
) r
ON s.Points BETWEEN r.start AND r.end;
I have inlined the table of ranges, but you may create a formal table (or maybe a temp table) instead, and then replace the above subquery with just a reference to that table.

Comparing Counts of the same column MySQL to get a percentage

What I need to do is the following:
Get a percentage of all class surveys in this program where the answer to question 1 was greater than 3.
I have a table that contains a huge dataset of classroom surveys. The issue is that GENE01, for example, might have 5 surveys done on it from 5 different students; so I have 4 classes, but 50 surveys associated with them.
So currently, I'm running two queries to accomplish this task, but I'd like for it to be one single query. Here are the two queries I'm looking to combine.
-- Query 1
SELECT COUNT(survey_ID) as total
FROM survey_Table
WHERE courseName LIKE 'GENE01'
OR courseName LIKE 'GENE02'
OR courseName LIKE 'GENE03'
OR courseName LIKE 'GENE04'
GROUP BY survey_ID WITH ROLLUP
;
-- Query 2
SELECT COUNT (survey_ID) as newTotal
FORM survey_Table
WHERE courseName LIKE 'GENE01' AND question1 > 3
OR courseName LIKE 'GENE02' AND question1 > 3
OR courseName LIKE 'GENE03' AND question1 > 3
OR courseName LIKE 'GENE04' AND question1 > 3
GROUP BY survey_ID WITH ROLLUP
;
Then I manually take a calculator from my desk and do newTotal / total * 100. I can't figure out the sub query (or whatever you need to do) to accomplish this simple task. The issue I guess I'm having is I don't know how to compare counts of the same column.
Thanks everyone, and sorry I'm pretty new to MySQL.
Conditional aggregation is a possible approach:
SELECT s.survey_ID
, SUM(1) AS total
, SUM(s.question1 > 3) AS newTotal
FROM survey_Table s
WHERE s.courseName IN ('GENE01','GENE02','GENE03','GENE04')
GROUP
BY s.survey_ID
WITH ROLLUP
Note the condition s.question1 > 3 is MySQL shorthand. MySQL evaluates that and returns 1 for TRUE, returns 0 for FALSE, and NULL if its null.
That's almost equivalent to the more portable ANSI-standards compliant:
SUM(CASE WHEN s.question1 > 3 THEN 1 ELSE 0 END) AS newTotal
There's a difference is in handling of NULL values.
A more precise rewrite of SUM(s.question1 > 3) would be
SUM(CASE WHEN s.question1 > 3 THEN 1 WHEN s.question1 IS NULL THEN NULL ELSE 0 END)
For each row returned, the expression inside the SUM() aggregate is evaluated. 1 always evaluates to 1.
Feel free to omit survey_ID from the SELECT list. Normally when we do a GROUP BY foo we're interested in which result row is associated with which foo.
The question asks about getting a "percentage". We can do division in an expression in the SELECT list. But I don't think the "with rollup" is going to get you what you what you are expecting.
Here's an example:
SELECT SUM(1) AS total
, SUM(s.question1 > 3) AS newTotal
, 100.0
* SUM(s.question1 > 3)
/ SUM(1) AS percentage
FROM survey_Table s
WHERE s.courseName IN ('GENE01','GENE02','GENE03','GENE04')
In this example, I've opted to omit a GROUP BY clause. So this will return a single overall total row, which would get us an overall percentage. (If we used a GROUP BY and WITH ROLLUP, the percentage would get added. And likely that's not the result we're after.)
You could join both the query by survey_id
select t1.survey_ID, t2.newTotal/t1.total
from (
SELECT survey_ID, COUNT (survey_ID) as newTotal
FORM survey_Table
WHERE courseName LIKE 'GENE01' AND question1 > 3
OR courseName LIKE 'GENE02' AND question1 > 3
OR courseName LIKE 'GENE03' AND question1 > 3
OR courseName LIKE 'GENE04' AND question1 > 3
GROUP BY survey_ID )
INNER JOIN (
SELECT survey_ID, COUNT(survey_ID) as total
FROM survey_Table
WHERE courseName LIKE 'GENE01'
OR courseName LIKE 'GENE02'
OR courseName LIKE 'GENE03'
OR courseName LIKE 'GENE04'
GROUP BY survey_ID ) t2. ON t1.survey_ID = t2.survey_ID