I'm pretty new to SQL and I need to figure out how to run multiple sums in the same statement. For example, imagine you have a table something like this...
+----+---------------+-------------+------------+-----------+
| id | name | order_num | cost | company |
+----+---------------+-------------+------------+-----------+
| 1 | John Smith | 0 | 10.00 | CompanyA |
| 2 | Sally Thomas | 1 | 38.00 | CompanyA |
| 2 | Sally Thomas | 2 | 12.00 | CompanyA |
| 1 | John Smith | 3 | 19.00 | CompanyA |
| 2 | Jimmy John | 4 | 40.00 | CompanyB |
+----+---------------+-------------+------------+-----------+
I would like to write a query that returns the name and total sum spent for each customer at CompanyA. So basically...
+---------------+------------+
| name | total |
+---------------+------------+
| John Smith | 29.00 |
| Sally Thomas | 50.00 |
| Jimmy John | 0.00 |
+---------------+------------+
To do that I know I'm going to need to use the sum function. But everything I've tried so far results in summing up the entire column rather than the individual parts for each person. This is just a simplified example of the bigger table I'm doing this on, so I don't know any of the field data beforehand. How can I do multiple sums in one query to get this result? Thanks!
Also, I'm using MySQL if it matters.
I think you want:
select name, sum(case when company = 'CompanyA' then cost else 0 end) as Total
from t
group by name;
Related
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();
Consider the following sample table from a soccer tournament (let's call this table matches)
+----------+---------+--------------+
| match_id | club_id | goals_scored |
+----------+---------+--------------+
| 1 | 1 | 1 |
| 1 | 2 | 0 |
| 2 | 1 | 1 |
| 2 | 3 | 1 |
| 3 | 1 | 0 |
| 3 | 4 | 2 |
| 4 | 2 | 2 |
| 4 | 3 | 4 |
| 5 | 2 | 4 |
| 5 | 4 | 0 |
| 6 | 3 | 1 |
| 6 | 4 | 1 |
+----------+---------+--------------+
The resulting table we want should give us each club's total goals scored AND goals conceded:
+---------+--------------+----------------+
| club_id | goals_scored | goals_conceded |
+---------+--------------+----------------+
| 1 | 2 | 4 |
| 2 | 6 | 4 |
| 3 | 6 | 4 |
| 4 | 3 | 5 |
+---------+--------------+----------------+
Getting goals scored is straight forward enough...
SELECT SUM(goals_scored),
club_id
FROM matches
GROUP BY club_id
but I am absolutely flummoxed as to how to get it for each team's opponents.
I could, of course, construct a pretty complex array of subqueries to get there. If this were application-side work I'd likely just stuff it in a loop and iterate over each club to get there, but my use case requires a SQL answer if possible. Any thoughts?
edit: also if anyone has any better ideas on how to title this question, I'm all ears - I'm not really sure exactly how to describe this problem in the first place.
We can use a self-join approach here:
SELECT
m1.club_id,
SUM(m1.goals_scored) AS goals_scored,
SUM(m2.goals_scored) AS goals_conceded
FROM matches m1
INNER JOIN matches m2
ON m2.match_id = m1.match_id AND
m2.club_id <> m1.club_id
GROUP BY
m1.club_id
ORDER BY
m1.club_id;
This approach brings the goals conceded by each club to the other club, for each match, into a single row. We then just aggregate by club to get the two sums.
I have 2 tables in MS Access with the following values
Customer
id | name
1 | jon
2 | bob
3 | jack
Order
id | amount | date | customer
5 | 50 | 3/10/2017 | 1
4 | 100 | 3/10/2017 | 1
3 | 45 | 2/28/2017 | 2
2 | 10 | 3/10/2017 | 3
1 | 5 | 3/10/2017 | 2
I want to get an output of
name | orderid | amount
jon | 5 | 50
bob | 3 | 45
jack | 2 | 10
I want to get amount of the latest order id per customer, however I keep getting this
name | orderid | amount
jon | 5 | 50
jon | 4 | 100
bob | 3 | 45
bob | 2 | 10
jack | 1 | 5
I used the query designer and have used the function MAX() to the order id, GROUP BY to all columns (MS Access does not allow to group the rows using a single column), DISTINCT and DISTINCTROW, as well as set the query properties "Unique Records" to Yes but the duplicate records still shows.
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
I've got a excel sheet that contains all the employees that have worked for my company and is still working for us. It's a sheet of around 200 rows. Each row has basic info, like surname, name, position, qualification etc etc. 16 columns of basic info. Now, the tricky part is this. After the 16 columns, there are months (May-05 up to the present (Apr-12)). Under every month column, an employee either get's a 0 (contract), 1 (permanent), 2 (contract-terminated) or 3 (student).
What would be the best way to do this? I was thinking of 4 tables (listed below), where the one table determines permanently terminated people (for the sake of knowing who was on what type of employment).
MySQL Table: hr_employees
|-----------------|-------|----|----|----|
| employee_number | name | sur| etc| etc|
|-----------------|-------|----|----|----|
| 1 | Dave | F | xx | xx |
|-----------------|-------|----|----|----|
MySQL Table: hr_month
|----|--------|
| id | month |
|----|--------|
| 1 | May-05 |
| 2 | Jun-05 |
|----|--------|
MySQL Table: hr_status
|----|------|------|--------|
| id | e_no | date | status |
|----|------|------|--------|
| 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 1 |
|----|------|------|--------|
MySQL Table: hr_terminated
|----|------|
| id | e_no |
|----|------|
| 1 | 1 |
| 2 | 1 |
|----|------|
I hope you guys understand what I want to achieve, otherwise, ask a question, and I'll answer as best I can! :)
Thanks.
Here is a design that simplifies your data entry and is more relational database like and less Excel like, insofar as it's normalized.
MySQL Table: hr_employee
|-----------------|-------|----|----|----|
| employee_number | name | sur| etc| etc|
|-----------------|-------|----|----|----|
| 1 | Dave | F | xx | xx |
|-----------------|-------|----|----|----|
| 2 | Bob | M | xx | xx |
|-----------------|-------|----|----|----|
MySQL Table: hr_employee_status
|-----------------|------------|------------|--------|
| employee_number | from_date | to_date | status |
|-----------------|------------|------------|--------|
| 1 | 2005-05-01 | 2005-08-31 | 3 |
|-----------------|------------|------------|--------|
| 1 | 2006-05-01 | 2010-02-28 | 0 |
|-----------------|------------|------------|--------|
| 2 | 2010-03-01 | 9999-12-31 | 1 |
|-----------------|------------|------------|--------|
Here you can see that Dave was hired on as a student from May '05 to August '05, then he came back in May '06 as a contract employee which he worked as until the end of February '10. Then on March 1, 2010 Bob was hired as permanent employee and he is still working (max collating date means "until further notice").
The great advantage of this design is that you only have to enter/edit data when something changes, not once a month for every employee that you have or have ever had. You can also see what your workforce looked like at any given date (not just by months!) with a very simple SQL query.