MySQL pull data from same table, SUM multiple columns with conditions - mysql

I have created a users table that holds names and phone numbers (users).
id| name | phone
1 | Frank | 0345221234
2 | Sara | 0342555939
I got another table that holds a log with user's calls to different numbers (call_logs):
number | destination | price
0345221234 | destination | x /// This is Frank
0345221234 | destination | y /// This is also Frank
0342555939 | destination | z /// This is Sara
And then I have a table that holds numbers that Frank and Sara are allowed to call (allowed_numbers):
number
033485733
045727728
082358288
I would like to loop through my users table and based on their number to check the calls log table and select the SUM of price column for log records where destination does not match the allowed numbers table so that I know the cost for calls not in the allowed list.
Then I want to select SUM of price column for log records where destination DO match
the allowed numbers table so that I know how much did the allowed calls cost.
Is there any way I can do this in a single query with sub-queries and all needed in order to achieve this result set:
users number | SUM(price) of allowed calls | SUM(price) of calls not allowed
Thank you!

SELECT call_logs.number
,SUM(IF(allowed_numbers.number IS NOT NULL,call_logs.price,0)) AS AllowedPrice
,SUM(IF(allowed_numbers.number IS NULL,call_logs.price,0)) AS NotAllowedPrice
FROM call_logs
LEFT JOIN allowed_numbers
ON call_logs.destination = allowed_numbers.number
GROUP BY call_logs.number;

Related

Aggregate data over multiple fields (not records)

id | segment1 |segment2|segment3|segment4|**FREQUENT**
1 | A | B | A | A | A
2 | B | C | C | C | C
Need to find the most frequent letters from segment1 |segment2|segment3|segment4| i.e to find column FREQUENT.
First of all you need to copy all the segments into a single column. One can do it using UNION or a temporary table.
Then you need to count the frequency grouping the result by ID.
Then you need to get the most frequent value in every group. It can be done using self joining over LEFT JOIN or using ordering and row numbering by group. It is the most complicated part. See
Row number per group in mysql
Then you filter by the row number and enjoy the result.

Count twice if certain condition satisfies in mysql

I have a scenario where I need to display total number of attendees of an event. With the help of registration form I have already captured the details of people who are attending and my table looks like below.
ID | NAME | PHONE_NUMBER | IS_LIFE_PARTNER_ATTENDING
1 | ABC | 1234567890 | N
2 | PQR | 1234567891 | Y
3 | XYZ | 1234567892 | N
I can easily display number of registrations by using count(id). But while displaying number of attendees I have to consider as two attendees if registrant is coming with his/her partner. (identified by IS_LIFE_PARTNER_ATTEDNING column)
So, in the above case, the number of registrants are 3, but number of attendees are 4, because "PQR" is coming with his/her life partner.
How can we do this in mysql query?
You can use the following query:
SELECT
SUM( 1 + (IS_LIFE_PARTNER_ATTEDNING = 'Y')) AS totalAttendees
FROM your_table;
WORKING DEMO
Since boolean expression resolves into 0/1 in MySQL so that you can capitalize this in your case.
Note:
SUM(a=b) returns 1 only if a is equal to b otherwise it returns 0
Caution:
*Never underestimate these parentheses (IS_LIFE_PARTNER_ATTEDNING = 'Y'). If you omit them then the whole summation would result in zero(0).
* because of operator precedence
Use SUM with CASE
SELECT
Name,
SUM(CASE WHEN IS_LIFE_PARTNER_ATTEDNING='y' THEN 2 ELSE 1 END ) AS'Attendes'
FROM
table
GROUP by name

How can I make a stored procedure to update one column in one table based on the order of rows from another table?

I have two tables
Users:
user | name | country | rank | country_rank | points
1 | frank | US | to be determined | to be determined | to be determined
Awards:
awarded_to | points_awarded
1 | 10
1 | 30
How can I make a stored procedure to update the users total points based off of the points from awards, then their rank and country_rank respectively based off of the order of the points (i.e. rank 1 would be the user with the most points)?
I considered making a PHP script and using a crontab to call it occasionally that would just select the info and do the math etc in PHP, but stored procedures seems much more practical for my use-case.
create temporary table awardsum (user int, total int); #temp
insert into awardsum
select a.awarded_to, sum(a.points_awarded)
from users u
inner join awards a on u.user=a.awarded_to
group by a.awarded_to;
update users
join awardsum on users.user=awardsum.user
set users.points = awardsum.total;
SELECT #row:=0;
UPDATE users
SET rank = (#row:=#row+1)
ORDER BY points desc;
drop table awardsum;

Microsoft Access 2003 Query - Count records and sum it

I'm creating a query with Microsoft Access 2003 and had encounter an issue. I'm new!
I've got 2 tables. First table, i have a list of records that include the name, property name and the country state. Second table, i have a list of property names, the number of units in the property and the property's country state.
I will like to count the number of records in the first table by its state, meanwhile summing up the number of units the property has in the state.
What I encountered is, when I sum the number of units, the units repeats!
Taking for example;
Table1:
Name | State | Property Name
Mr 1 | State A | Building AAA
Mr 2 | State A | Building AAA
Mr 3 | State A | Building BBB
Mr 4 | State B | Building XXX
Mr 5 | State B | Building XXX
Table2:
Property Name | State | Number of Units
Building AAA | State A | 100
Building BBB | State A | 50
Building XXX | State B | 20
My Result:
State | Number of Units | No of Records
State A | 250 | 3
State B | 40 | 2
The result i want:
State | Number of Units | No of Records
State A | 150 | 3
State B | 20 | 2
EXPANDED
Assuming you are using the Access query builder, you will need to construct three Select queries:
1) Table1 will be the source table for the first query. Use the State field twice in the query, first as a Group By field and second as a Count field. (Any of the fields could have been used for the count, since you are only interested in the number of records.) Save the query for use in the third query.
2) Table2 will be the source table for the second query. Use the State field as a Group By field and the Units field as a Sum field. Save this query, too.
3) The third query will bring the information together. For the source, use the first and second queries, with a join between them on the State field. Select the State field (from either query) as a Group By Field, the CountOfState field from the first query as a Sum field, and the SumofUnits field from the second query as a Sum field.
While the actual amount of work done by Access in producing the final result will not change, the three queries can be consolidated into a single query by editing the underlying SQL.
The new query was produced by inserting the Table1 and Table2 queries into the third, final result query, one on either side of the INNER JOIN statement. The T1 and T1 in the new query are aliases for the embedded queries that eliminate ambiguity in referencing the fields of those queries.
The new query cannot be created using the Query Builder (although the original three queries provide the raw material for it). Instead, the SQL must be written/pasted in/edited in the SQL View of the Query Builder.
SELECT T1.State AS State,
Sum(T1.CountOfState) AS Records,
Sum(T2.SumOfUnits) AS Units
FROM
(SELECT Table1.State,
Count(Table1.State) AS CountOfState
FROM Table1
GROUP BY Table1.State) T1
INNER JOIN
(SELECT Table2.State,
Sum(Table2.Units) AS SumOfUnits
FROM Table2
GROUP BY Table2.State) T2
ON T1.State = T2.State
GROUP BY T1.State;

MySQL query to search for all records against field with comma separated values

I have 2 sql tables
Table name: agents contains a records with a coloumn AgentID
Table named: vacancies is the one with the data ans is being dislayed.
Table named vacancies has vacancies.Agents which contains values simmilar to this
VacanyID Company position CTC Candidates Agents
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
FBVAC001 | HDFC | Branch Manager | 4.5 | FBCAN001,FBCAN002| Agent3,Agent4
FBVAC003 | TBNH | Branch Manager | 4.5 | FBCAN004,FBCAN005| Agent2,Agent4
FBVAC005 | MMNT | Branch Manager | 4.5 | FBCAN008,FBCAN006| Agent3
FBVAC008 | LCFC | Branch Manager | 4.5 | FBCAN009,FBCAN023| Agent3,Agent4
FBVAC008 | KOTC | Branch Manager | 4.5 | FBCAN009,FBCAN023| Agent5,Agent4
I want to run a query that will return only those records that contain the value that corresponds to agents.AgentID from table name agents. This is the query so far but all it returs are those records that do not have more than one value in vacancies.Agents
for example if the value being searched for is Agent3 it should return rows1,3 and 4 instead it only returns row 3.
SELECT
vacancies.VacancyID,
vacancies.Company,
vacancies.`Position`,
vacancies.CTC,
vacancies.Candidates,
vacancies.Agents
FROM vacancies
, agents
WHERE (FIND_IN_SET(vacancies.Agents,agents.AgentID) <> 0)
How can this be resolved?
I believe you have your parameters backwards in FIND_IN_SET. The set should come second
FIND_IN_SET(agents.AgentID, vacancies.Agents)
More Info: http://www.bitbybit.dk/carsten/blog/?p=162
Also, if you are wanting to see only a specific agent, you need to filter for that as well, otherwise you're getting every possible combination of agent and matching vacancies (hence the duplicate rows):
AND Agents.AgentID = 'Agent3'
Demo: http://www.sqlfiddle.com/#!2/b4dcb/3
SELECT
vacancies.VacancyID,
vacancies.Company,
vacancies.`Position`,
vacancies.CTC,
vacancies.Candidates,
vacancies.Agents
FROM vacancies,
agents
WHERE (select
agents.agentid,
vacancies.agentid
from agents
left join vacancies
on vacancies.agentid = agents.agentid)
and agents.agentid = 'Agent3'