MySql search ranking with criteria - mysql

I have table named customers that keeps the customer's data
id | fname | lname
--- | ------ | ------
1 | John | Smith
2 | Mike | Bolton
3 | Liz | John
4 | Mark | Jobs
And i have another table named calls that keeps each call made to each customer.
id | timestamp | customer_id | campaign | answered |
1 |2016-09-05 15:24:08| 1 | 2016-09 | 1 |
2 |2016-09-05 15:20:08| 2 | 2016-09 | 1 |
3 |2016-08-05 15:20:08| 2 | 2016-08 | 1 |
4 |2016-08-05 13:20:08| 3 | 2016-08 | 1 |
5 |2016-08-01 15:20:08| 3 | 2016-08 | 0 |
5 |2016-08-01 12:20:08| 4 | General | 1 |
Campaign General Doesn't count towards the calculations.
I need to get a list of customers ordered by ranking of calling quality based on each customer calling history.
This list is use to call the customers in order that:
Hasn't been called on the actual calling campaign (ex.2016-09)
Has fewer calls
Best % answered (total calls answered / total calls made)
It should look something like this:
| id | fname | lname | %ans | called actual campaign | total calls | rank |
|----|--------|-------|------|------------------------|-------------|------|
| 4 | Mark | Jobs | N/A | no | 0 | 1 |
| 3 | Liz | John | 50 | no | 2 | 2 |
| 1 | John | Smith | 100 | yes | 1 | 3 | No Show
| 2 | Mike | Bolton| 100 | yes | 2 | 4 | No Show
Please help me!

The query which counts for each customer total calls and answered calls for the specified campaign
select
c.id,
count(*) as total_calls,
sum(case when answered=1 then 1 else 0 end) as answered_calls
from customer c
join calls cs on c.id=cs.customer_id
where cs.campaign='2016-09'
group by c.id
Then you can use the query above as a subquery to order
select sub.id, (#rank:=#rank+1) as rank
from (the subquery above) sub, (select #rank:=1)
order by
case when sub.total_calls=0 then 0 else 1,
sub.total_calls,
sub.answered_calls*100/sub.total_calls
You can include any desired columns in the result query

Related

Join 2 tables and sum with condition in codeigniter

I have 2 tables
Table1: customers:
-------------
| id | name |
-------------
| 1 | Mark |
-------------
| 2 | Tom |
-------------
| 3 | John |
Table2: sales:
-----------------------------------
|sid | customerid | price | state |
-----------------------------------
| 10 | 1 | 12000 | 0 |
-----------------------------------
| 11 | 2 | 13500 | 1 |
-----------------------------------
| 12 | 2 | 23000 | 1 |
-----------------------------------
| 13 | 3 | 26000 | 0 |
-----------------------------------
| 14 | 1 | 66000 | 1 |
-----------------------------------
the state column is 0=no dep and 1=dept
I want to list the customers that have DEPT by checking them in the sales table. Now i'm looping the customers and checking them one by one. and it works! but when the number of rows in the customer table grows the page slows down. i want to make this by an SQL query. can anyone help me please ?
the result will be like this:
Mark 66000
Tom 36500
By the Following query, you will get the same output as you want. The joining of tables will be executed on the filtered data using where condition
$this->db->select('customers.name,sum(sales.price)')
->from('customers')
->join('sales','sales.customerid = customers.id','left')
->where('sales.state !=0')
->group_by('customers.name');
->get()->result_array();
You can simply group by customer id in sales table. Code will be like this
return $this->db->select('MAX(customers.name) AS name, SUM(sales.price) as price')->join('sales', 'sales.customerid = customers.id')->where('sales.state', 1)->group_by('customers.id')->get('customers')->result();

MySQL return total COUNT of each value in a column

I have a table of jobseekers
with three columns
JOBSEEKER ID, EMPLOYER ID, HIRING STATUS
Each jobseeker could have different hiring
status for each employer depending on the interview.
Now I want to return the
COUNT of each total HIRING STATUS
But it should only count the jobseeker's
highest hiring status.
Say that John was
ranked as QUALIFIED by employer 1
and HIRED by employer 2
John will only be counted under the highest
hiring status he got which is HIRED by employer 2
and must not be counted under QUALIFIED.
HIRED: 1
QUALIFIED: 0
NEAR HIRED: 0
NOT QUALIFIED: 0
Here is my table
| Jobseeker Id | Employer Id | hstatus_id |
|--------------|-------------|------------------|
| 1 | 2 | 1(Hired) |
| 2 | 3 | 1(Hired) |
| 2 | 4 | 3(Near Hire) |
| 3 | 4 | 4(Not Qualified) |
| 1 | 2 | 2(Qualified) |
| 3 | 3 | 1(Hired) |
| 4 | 2 | 3(Near Hire) |
and the result I want is
| Hiring Status | COUNT |
|---------------|-------|
| Hired | 3 |
| Qualified | 0 |
| Near Hire | 1 |
| Not Qualified | 0 |
Thank you, sorry for bad English.
You need a LEFT join of the table hStatus_table to a query that returns the minimum integer hiringstatus of each jobseekerid:
select s.hiringstatus, count(t.jobseekerid) counter
from hStatus_table s
left join (
select jobseekerid, min(hstatus_id) hstatus_id
from tablename
group by jobseekerid
) t on t.hstatus_id = s.id
group by s.id, s.hiringstatus
I assume that the table hStatus_table is like this:
| ID | HiringStatus |
| --- | ------------- |
| 1 | Hired |
| 2 | Qualified |
| 3 | Near Hire |
| 4 | Not Qualified |
See the demo.
Results:
| hiringstatus | counter |
| ------------- | ------- |
| Hired | 3 |
| Qualified | 0 |
| Near Hire | 1 |
| Not Qualified | 0 |
You can use window functions for this:
select hiring_status, sum(seqnum = 1)
from (select js.*,
row_number() over (partition by Jobseeker_id order by hiring_status desc) as seqnum
from jobseekers js
) js
group by hiring_status;
This assumes that hiring_status is either a number or a string that starts with the appropriate digits.
It also assumes that all hiring_status values are in jobseekers.
EDIT:
If the ids are stored in another table, then you would simply use a left join:
select hs.*, count(js.job_seeker)
from hstatus_table hs left join
(select js.job_seeker, max(hs.hiring_status_id) as max_hiring_status_id
from jobseekers js
group by js.job_seeker
) js
on hs.hiring_status_id = max_hiring_status_id
group by hs.hiring_status_id;

Join 3 tables up count the highest user in one table

I'm trying 3 join tables so i can report who has the highest calls for each single customer please see the tables below
+-------+--+------------+
| users | | |
+-------+--+------------+
| id | | first name |
| 1 | | Bill |
| 2 | | Ben |
| 3 | | Bob |
| 4 | | Barry |
+-------+--+------------+
the second table is a call customers table
+-----------+--+-------------------+
| customers | | |
+-----------+--+-------------------+
| id | | Company |
| 1 | | windows company |
| 2 | | glass company |
+-----------+--+-------------------+
the third table is the where to calls are record
+-------------+--+--------+--------------+
| callrecords | | | |
+-------------+--+--------+--------------+
| id | | userid | company id |
| 1 | | 1 | 1 |
| 2 | | 1 | 1 |
| 3 | | 1 | 1 |
| 4 | | 2 | 1 |
| 5 | | 2 | 2 |
| 6 | | 2 | 2 |
+-------------+--+--------+--------------+
So as you can see in the call record table company id 1 which is the windows company has had 4 calls but user 1 made the most so that company i need to display bill company id 2 which is the glass company need to display user id 2 because they made 2 calls in total and not user id 1 because they only made 1 call
so the mysql query i need to make needs to loop round so the report looks like this
windows company - most calls bill
glass company - most calls Ben
If you want a single query that will fetch records. You can check below query. This will give you highest calls for each single customer.
SELECT CR.companyid, C.company, U.first_name, COUNT(CR.userid) AS callCount
FROM callrecords AS CR
INNER JOIN customers AS C ON (C.id= CR.companyid)
INNER JOIN users AS U ON (U.id= CR.userid)
GROUP BY C.id,CR.userid HAVING callCount = (
SELECT count(callrecords.userid) as count
FROM callrecords
WHERE callrecords.companyid = CR.companyid
GROUP BY callrecords.userid
ORDER BY count DESC
LIMIT 1
);
Ignore spells of table or column name because table's or column's name in question is not well formatted.

MySQL Limit Results Based on Join Table

I have 2 tables,but linked in many to many relations so 3 tables :
Table Author :
idAuthor,
Name
+----------+-------+
| idAuthor | Name |
+----------+-------+
| 1 | Renee |
| 2 | John |
| 3 | Bob |
| 4 | Bryan |
+----------+-------+
Table Publication:
idPublication,
Title,
Type,
Date,
Journal,
Conference
+---------------+--------------+------+-------------+------------+-----------+
| idPublication | Title | Date | Type | Conference | Journal |
+---------------+--------------+------+-------------+------------+-----------+
| 1 | Flower thing | 2008 | book | NULL | NULL |
| 2 | Bees | 2009 | article | NULL | Le Monde |
| 3 | Wasps | 2010 | inproceding | KDD | NULL |
| 4 | Whales | 2010 | inproceding | DPC | NULL |
| 5 | Lyon | 2011 | article | NULL | Le Figaro |
| 6 | Plants | 2012 | book | NULL | NULL |
+---------------+--------------+------+-------------+------------+-----------+
Table author_has_publication :
Author_idAuthor,
Publication_idPublication
+-----------------+---------------------------+
| Author_idAuthor | Publication_idPublication |
+-----------------+---------------------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 1 | 5 |
| 2 | 5 |
| 3 | 5 |
| 3 | 6 |
+-----------------+---------------------------+
What I want to do is get the top X author having the most publications.
I achieved to get the result avec the idAuthor having the most publications, using this request :
SELECT Author_idAuthor, COUNT(*) as count FROM Author_has_publication GROUP BY Author_idAuthor ORDER BY count DESC;
I get the list of the authors id, ordered by the number of publications :
+-----------------+-------+
| Author_idAuthor | count |
+-----------------+-------+
| 3 | 3 |
| 2 | 2 |
| 1 | 2 |
| 4 | 1 |
+-----------------+-------+
but then when I try to select the author corresponding to the top X of the result set of the previous query I have an error
I am Trying this SELECT TOP 2 FROM author WHERE (SELECT Author_idAuthor, COUNT(*) as count FROM Author_has_publication GROUP BY Author_idAuthor ORDER BY count DESC)=idAuthor;
I think it might be because my inside query return 2 rows, and I do a simple SELECT here or that I need a JOIN but i have no ideas how to use it here.
MySQL has no TOP keyword. It does however have a LIMIT keyword. Your query is invalid anyway.
There are a couple of options here. The following is an example of a correlated subquery: https://en.wikipedia.org/wiki/Correlated_subquery
SELECT
a.idAuthor,
a.Name ,
(SELECT COUNT(*) from author_has_publication ahp WHERE
ahp.Author_idAuthor = a.idAuthor) AS publication_count
FROM
author a
ORDER BY
publication_count DESC
LIMIT 2
As the referenced article notes, the above is inefficient as the subquery needs to be re-executed for each row of the result. If you do not actually need the count in the resultset then the below would be more efficient as the subquery is non-correlated and executed only once.
SELECT
a.idAuthor,
a.Name
FROM
author a
INNER JOIN
(select ahp.Author_idAuthor AS idAuthor, COUNT(*) as publication_count
FROM author_has_publication ahp GROUP BY ahp.Author_idAuthor LIMIT 2)
AS TEMP ON TEMP.idAuthor = a.idAuthor

sql query to find users with at least 2 types of accounts

I'm new to relational sql. I'm trying to figure out a query to return the names of customers who have more than one type of account.
customers:
+------------+--------------+
| cid | Name |
+------------+--------------+
| 1 | Bob |
| 2 | John |
| 3 | Jane |
+------------+--------------+
accounts:
+------------+--------------+
| aid | type |
+------------+--------------+
| 1 | Checking |
| 2 | Saving |
| 3 | CD |
+------------+--------------+
transactions:
+------------+--------------+--------------+
| tid | cid | aid |
+------------+--------------+--------------+
| 1 | 1 | 1 |
| 2 | 2 | 1 |
| 3 | 1 | 2 |
| 4 | 2 | 3 |
| 5 | 3 | 1 |
+------------+--------------+--------------+
With these tables, the query should return Bob and John. I'm having some trouble with how to write such a query. More specifically, how do I keep count of how many accounts a customer has and how do I compare if the accounts are different without adding a new column to the table?
Okay, this seems to work in SQL Fiddle with my test data structure. Try it out with your real data structure and see if it gives you what you're looking for.
SELECT name FROM customers c WHERE EXISTS(
SELECT DISTINCT aid FROM transactions
WHERE cid = c.cid
HAVING COUNT(DISTINCT aid)>1
)