Is there any way to use advanced Count? - mysql

I have 3 tables named team, customer, and documents.
`team` contains ID, Name
`customer ` contains ID, teamID, Name
`documents ` contains ID, documentID, customerId, Name
What i want to achieve is the count of customer per team, and count of customer document.
NB: a customer must have 2 documents, if a customer does not have a document it is regarded as 'incomplete' and vice-versa.
below is the table structure
team table
ID
Name
123
Lagos
134
Abuja
137
Niger
customer table
ID
teamID
Name
234
123
John
254
134
Hannah
259
137
Josiah
document table
ID
documentID
customerId
Name
354
456
234
47hhhgj.jpg
358
466
254
66tyhgg.pdf
360
466
234
7384848.pdf
362
456
254
jf6fjfo.jpg
368
466
259
yj77799.pdf
Result
team
Number of customer
complete
incomplete
Lagos
200
30
170
Abuja
100
50
50
The query used is below:
SELECT b.team, COUNT(a.Name) FROM customer a inner join team b on a.teamID = b.ID
but was unable to compute for complete and in complete column and i've tried a lot of approach
So from the result table, team Lagos as 200 customer, 30 customers have complete document
and 170 customers have incomplete document etc.
Thanks.

First we need to know how to find complete customers. To this we join the documents to the customer and get the count
SELECT c.ID, c.teamid, count(d.id) as doc_count,
CASE WHEN count(d.id) >= 2 THEN 1 ELSE 0 END as complete_flag,
CASE WHEN count(d.id) >= 2 THEN 0 ELSE 1 END as incomplete_flag
FROM customer c
LEFT JOIN document d on c.ID = d.customerid
GROUP BY c.ID, c.teamid
You can see I also added a flag here for complete and incomplete -- you don't need to calculate both here but I think it is faster to do them both at the same time -- it makes the next query simple:
SELECT t.name as team, COUNT(s.id) as num_of_customers,
SUM(complete_flag) AS complete,
SUM(incomplete_flag) AS incomplete
FROM team t
LEFT JOIN (
SELECT c.ID, c.teamid, count(d.id) as doc_count,
CASE WHEN count(d.id) >= 2 THEN 1 ELSE 0 END as complete_flag,
CASE WHEN count(d.id) >= 2 THEN 0 ELSE 1 END as incomplete_flag
FROM customer c
LEFT JOIN document d on c.ID = d.customerid
GROUP BY c.ID, c.teamid
) AS s ON t.id = s.teamid
GROUP BY t.id, t.name

Related

Using group_concat With a Condition: Display 0 if Values are Not Equal

I just want to display column fields horizontally but also putting a condition to it. Display zero if it has not met the condition.
Example problem: Find the PAYCODE 912 and 686 and display the amount, if not available, display 0
my_table
EMPLOYEE
PAYCODE
AMOUNT
1
912
1
1
123
3
2
912
5
2
686
7
3
111
4
Output must be:
EMPLOYEE
AMOUNT
1
1,0
2
5,7
3
0,0
My code so far:
SELECT
EMPLOYEE,
GROUP_CONCAT(DISTINCT CONCAT(
IF(PAYCODE = '912', AMOUNT, '0'),
IF(PAYCODE = '686', AMOUNT, '0'))
SEPARATOR',') as AMOUNT
FROM
my_table
Note: There are no duplicate paycodes on a similar employee. e.g. two 912 paycodes
I'm thinking a cross join approach should work here:
SELECT e.EMPLOYEE,
GROUP_CONCAT(COALESCE(t.AMOUNT, 0) ORDER BY e.PAYMENTTYPE DESC) AS AMOUNT
FROM (SELECT DISTINCT EMPLOYEE FROM my_table) e
CROSS JOIN (SELECT '912' AS PAYMENTTYPE UNION ALL SELECT '686') p
LEFT JOIN my_table t
ON t.EMPLOYEE = e.EMPLOYEE AND
t.PAYMENTTYPE = p.PAYMENTTYPE
GROUP BY e.EMPLOYEE;
The cross join between the e and p subqueries generates all employee/payment type combinations of interest (only types 912 and 686). We then left join to your table to bring in the amounts, which if are missing we report 0 instead.

show who resit and passed and what course was it?

i need help find who fail in exam & resit and pass the exam only,
heres the code:
select STUDENT_ID,EXAM_ID,SCORE,PASS_THRESHOLD,s.NAME , c.NAME as Course_name, EXAM_DT,
case
when SCORE>=PASS_THRESHOLD then 'PASS'
else 'Fail'
end as Flag
from exam_submission es
left join student s on es.STUDENT_ID = s.ID
left join exam e on es.EXAM_ID = e.ID
left join course c on e.COURSE_ID = c.ID
heres the result:
STUDENT_ID EXAM_ID SCORE PASS_THRESHOLD NAME Course_name EXAM_DT Flag
1 3 88 65 Anthony Data Mining 2019-12-17 PASS
1 5 71 70 Anthony Statistic 2019-12-19 PASS
2 1 53 55 Sisca Machine Learning2019-12-17 Fail
2 3 77 65 Sisca Data Mining 2019-12-17 PASS
2 4 85 63 Sisca Data Science 2019-12-18 PASS
2 1 60 55 Sisca Machine Learning2020-01-08 PASS
I need find like this:
2 1 53 55 Sisca Machine Learning2019-12-17 Fail
2 1 60 55 Sisca Machine Learning2020-01-08 PASS
Possibly using a query like below.
this is using your query as input.
Also we have assumed that it is not possible to have a student have (PASS, FAIL) for a student on same exam on two years chronologically.
; with inputdata as
(
select STUDENT_ID,EXAM_ID,SCORE,PASS_THRESHOLD,s.NAME , c.NAME as Course_name, EXAM_DT,
case
when SCORE>=PASS_THRESHOLD then 'PASS'
else 'Fail'
end as Flag
from exam_submission es
left join student s on es.STUDENT_ID = s.ID
left join exam e on es.EXAM_ID = e.ID
left join course c on e.COURSE_ID = c.ID
)
select * from Inputdata I
join
( select student_id, exam_id from
inputdata
group by student_id, exam_id
having count(distinct flag)=2
)T on I.student_id=T.student_id and I.exam_id=T.exam_id
order by exam_dt asc

Writing a LIMIT subquery within my SQL query

So I have the following query which fetches active competitions for an organisation, but also aims to fetch the user that is in the lead - for each competition fetched.
The query currently works in that it fetches the competitions, however it currently fetches all the users and I would like to LIMIT 1 on the users fetched, using the SUM(activity_weight) you can see below.
The results come out like this (removed some results to make it easy to see) and in my case, I only want to fetch John and Sally, as they are the leaders of the competitions.
competitionId compName start_date end_date name totalPoints
------------------------------------------------------------
123 First Comp 13-09-09 13-10-09 John 100
123 First Comp 13-09-09 13-10-09 Bob 50
431 Second Comp 13-05-04 13-10-05 Sally 500
431 Second Comp 13-05-04 13-10-05 Jessica 50
I understand that I must use some form of subquery to use the LIMIT, but having a problem nailing the syntax of it.
Any help is much appreciated! THANK YOU
SELECT c.competitionId, c.name, c.start_date, c.end_date, a.userid, u.name,
u.profilePic ,
SUM(activity_weight) AS totalPoints
FROM activity_entries a INNER JOIN users1 u ON u.id = a.userid
INNER JOIN competitions c ON c.competitionId = a.competitionId
WHERE c.organisationId = '$organisation' AND c.start_date < now() AND c.end_date > now()
GROUP BY a.userid, c.competitionId ORDER BY c.id DESC, totalPoints DESC
Try this query
select * from
(select
#rn:=if(#prv=competitionId , #rn+1, 1) as rId,
#prv:=competitionId as competitionId ,
totalPoints,
your_other_columns
from (select * from ...)subquery
join
(select #prv:=0, #rn:=0)tmp
order by
competitionId , totalPoints desc) a
-- only top 2 ordered by points for every competition
where rid<=2
output:
rID competitionId compName start_date end_date name totalPoints
------------------------------------------------------------
1 123 First Comp 13-09-09 13-10-09 John 100
2 123 First Comp 13-09-09 13-10-09 Bob 50
1 431 Second Comp 13-05-04 13-10-05 Sally 500
2 431 Second Comp 13-05-04 13-10-05 Jessica 50
change the last part to where rid<=1 to select top 1

How to join 3 table with this condition?

I have 3 tables: product, customer and transaction.
Product:
id_product price
1 1000
2 2000
Customer:
id_customer name
1 Tom
2 Jack
Transaction:
id_transaction id_product id_customer qty date
1 1 1 10 2013-02-21
2 2 1 50 2013-02-21
3 1 2 15 2013-02-21
I want to achieve this result:
id_customer name total_transaction purchase_qty subtotal
1 Tom 2 60 110000
2 Jack 1 15 15000
How I can get that result using a query in MySQL?
SELECT t.id_customer, c.name,
COUNT(t.id_customer) AS total_transaction,
SUM(t.qty) as purchase_qty
FROM transaction t
INNER JOIN customer c
ON t.id_customer = c.id_customer
GROUP BY t.id_customer,c.name
SELECT cs.id_customer, cs.name, COUNT(tr.transaction) AS total_transaction, SUM(tr.qty) as purchase_qty, SUM(tr.qty*pr.prize)
FROM customer AS cs
LEFT JOIN transaction AS tr ON tr.id_customer = cs.id_customer
LEFT JOIN product AS pr ON pr.id_product = tr.id_product
GROUP BY cs.id_customer
I suppose you are a total beginner, so I did this for you. Next time, if you have ANY own ideas, give to us, so we don't have to write the whole query for you. Show some effort.
SELECT c.id_customer, c.name, count(t.id_transaction) AS total_transaction
FORM Customer c INNER JOIN Transaction T
ON C.id_customer = T.id_customer
GROUP BY c.id_customer
You need a group by statement since you want to aggregate results for a given customer :
SELECT id_customer, name, count(id_transaction) AS total_transaction
FORM Customer, Transaction
WHERE Transaction.id_customer = Customer.id_customer
GROUP BY id_customer
This does not solve your whole problem, but you've got the idea.

having trouble writing a query that list all salesmen that did not sell to a particular customer

I was successful in writing the query that lists salesmen that did sell to a particular customer, but not those that have not. I suspect it is because the same salesmen that sold to the specific customer, also sold to other customers.
select a.name from salesperson a inner join orders b on
a.salesperson_id = b.salesperson_id where cust_id="4";
I was thinking that modifying the same query like this would do the trick:
.... a.salesperson_id <> b.salesperson_id where cust_id="4";
But the result lists all the salesmen. This is most likely due to the fact that the same salesmen that were returned in the original query, also sold to other customers
The 3 tables look like this:
Salesperson table
salesperson_ID, Name, Age, Salary
1 Abe 61 140000
2 Bob 34 44000
5 Chris 34 40000
7 Dan 41 52000
8 Ken 57 115000
11 Joe 38 38000
Customer table
cust_ID, Name, City Industry Type
4 faralon sacramento H
6 Apple cupertino S
7 Honda NY B
9 Kolb Oshkosh B
Orders table
Number, Order_date, cust_id, salesperson_id, Amount
10 8/2/1996 4 2 540
20 1/30/1999 4 8 1800
30 7/14/1995 9 1 460
40 1/29/1998 7 2 2400
50 2/3/1998 6 7 600
60 3/2/1998 6 7 720
70 5/6/1998 9 7 150
Any help would be greatly appreciated. ~Alpinehyker
You can do something like this:
select a.name from salesperson a
left join orders b on a.salesperson_id = b.salesperson_id and b.cust_id="4"
where b.Number is null
So, get all salepersons, left join to orders for customer 4, and return only rows where there is no such order.
I am assuming that Number is the primary key for Orders, or at least not null.
All salespeople who have NOT sold to customer_ID 4:
SELECT s.Name FROM Salesperson AS s
LEFT JOIN Orders AS o
ON s.salesperson_ID = o.salesperson_ID
WHERE o.customer_ID <> 4
GROUP BY o.salesperson_ID;
Perhaps this will work
SELECT
s.*
FROM `Salesperson` AS s
LEFT JOIN `Orders` AS o ON o.`salesperson_id` = s.`salesperson_ID`
WHERE
o.`cust_id` NOT IN (4)
GROUP BY s.`salesperson_ID`;
Answer to your 2nd question:
SELECT
COUNT(*) AS num_of_orders
,s.`Name`
FROM `Salesperson` AS s
LEFT JOIN `Orders` AS o ON o.`salesperson_id` = s.`salesperson_ID`
GROUP BY s.`salesperson_ID`
HAVING num_of_orders >= 2;
...and 3rd question. (assuming you have your highAchiever table ready)
INSERT INTO `highAchiever`
(`Name`,`Age`)
SELECT
`Name`
,`Age`
FROM `Salesperson`
WHERE
`Salary` >= 100000;