This question already has an answer here:
MySQL SUM() giving incorrect total
(1 answer)
Closed 6 years ago.
I have two table on (daily_book and extra_cost) so structure is
daily_book
db_id | refund
1 | 7161
2 | 5980
extra_cost
ec_id | db_id | cost
1 | 1 | 156
2 | 1 | 123
3 | 2 | 100
4 | 2 | 120
So I get total refund value and total cost value in one row.
So my query is
$sql = "SELECT SUM(d.refund) AS refund, SUM(e.cost) AS e_cost FROM `daily_book` d LEFT JOIN extra_cost e ON (d.db_id = e.db_id) WHERE d.db_id > 0";
I got result is 26,282 for refund and 499 for total cost; that's incorrect.
I want result is 13,141 for refund and 499 for total cost.
There is no mystery here. You are aggregating multiple rows for the refund. You need to do the aggregations separately. In MySQL, this is a bit cumbersome, but here is one method:
SELECT dd.refund, SUM(e.cost) AS e_cost
FROM daily_book d LEFT JOIN
extra_cost e
ON (d.db_id = e.db_id) CROSS JOIN
(SELECT SUM(d.refund) as refund FROM daily_book d WHERE d.db_id > 0) dd
WHERE d.db_id > 0;
Related
I have two tables, 'authorization' and 'transaction'.
authorization table
Auth_ID | User_ID | Auth_Hours
-------------------------------
5 | 1 | 60
6 | 2 | 40
7 | 3 | 50
transaction table
Auth_ID | User_ID | Used_Hours
-------------------------------
5 | 1 | 5
6 | 2 | 2
5 | 1 | 20
6 | 2 | 17
5 | 1 | 11
6 | 2 | 9
I want my query to sum Used_Hours and group by Auth_ID and User_ID from the transaction table. Here's the catch - I also want the query result to show users who have not used any of their Auth_Hours with a 0. See below:
QUERY
SELECT a.Auth_ID, a.USER_ID, a.Auth_Hours, SUM(t.Used_Hours)
FROM AUTHORIZATION a
JOIN TRANSACTION t
on a.Auth_ID = t.Auth_ID
and a.User_ID = t.User_ID
GROUP BY a.Auth_ID, a.USER_ID, a.Auth_Hours
Actual Result
Auth_ID | User_ID | Auth_Hours | Total Hours Used
-------------------------------------------------
5 | 1 | 60 | 36
6 | 2 | 40 | 28
Wanted Result
Auth_ID | User_ID | Auth_Hours | Total Hours Used
-------------------------------------------------
5 | 1 | 60 | 36
6 | 2 | 40 | 28
7 | 3 | 50 | 0
I would imagine the query to be relatively simple.
The JOIN statement is a shortcut for INNER JOIN which returns records that have matching values in both tables. If you want to return all records from one table and the matching records from the other table, then you should use an outer join (LEFT [OUTER] JOIN or RIGHT [OUTER] JOIN). Then you can use the IFNULL() or COALESCE()functions to convert NULLs to zeros:
SELECT a.Auth_ID, a.USER_ID, a.Auth_Hours, IFNULL(SUM(t.Used_Hours), 0) AS 'Total Hours Used'
FROM authorization a
LEFT JOIN transaction t ON a.Auth_ID = t.Auth_ID AND a.User_ID = t.User_ID
GROUP BY a.Auth_ID, a.USER_ID, a.Auth_Hours
Notice that I used single quotes to assign a string with spaces as a name to the total field (as you used in your examples). This will work in all databases. In MySQL you can also use back ticks, but that only works in MySQL.
Here is a good illustration about the different types of joining tables.
this query work in any mysql Engine or Version. use this query:
SELECT a.Auth_ID, a.USER_ID, a.Auth_Hours, CASE COUNT(t.Used_Hours) WHEN 0 THEN 0 ELSE SUM(t.Used_Hours) END AS 'Total Hours Used'
FROM authorization a
LEFT JOIN TRANSACTION t ON a.Auth_ID = t.Auth_ID AND a.User_ID = t.User_ID
GROUP BY a.Auth_ID, a.USER_ID, a.Auth_Hours
What I want to do is generate a similarity percentage amount by comparing a ratings column from one table with the ratings column from another table.
However, this needs to be limited to instances where an id from one table matches an id in another table, is for a specific user and a rating exists in the ratings column from both tables.
For example, table1 has the following columns and data:
id | rate (out of 10)
=====================
1 | 8
2 | 10
3 | 5
4 | 4
5 | 0
6 | 9
7 | 8
And table2 has the following columns and data:
movid | userid | rating (out of 10)
================================
1 | 3 | 6
2 | 2 | 10
3 | 1 | 4
4 | 3 | 7
5 | 3 | 6
6 | 4 | 8
7 | 3 | 5
So lets say I want to use any rows where 'userid' = 3 and compare their 'rating' from table2 to the 'rate' column from table1 where 'rate' > 0 and id/movid from the two tables has the same number.
Using the example above, the results to compare should be limited to:
id | rate
=====================
1 | 8
4 | 4
7 | 8
movid | userid | rating
================================
1 | 3 | 6
4 | 3 | 7
7 | 3 | 5
Even though userid 3 had a rating for movid 5 in table2, it had a 0 rate (no rating) for id 5 in table1, so it will not compare those.
This would compare the ratings for each id/movid and then put it into an overall total. As the rating numbers are based on a score out of 10, I'm guessing the best way to determine the similarity percentage is to take the difference between each id/movid, subtract it from 10 to get the percentage number.
For id/movid 1, 'rate' in table1 is 8 and 'rating' in table2 is 6. The difference between those numbers is 2. We subtract 2 from 10, to get 80% similarity score for id/movid 1.
That would need to happen for each comparison and then total it all together.
So by my calculation, the similarity score for id/movid 1, 4 and 7 all combined would be 73% (rounded without decimals).
This total percentage amount is the end result I am trying to achieve. Can anyone help me out? I'm now bald after all of the hair I've pulled out trying to get this to work.
SELECT ROUND(SUM(10-ABS(table1.rate-table2.rating))*10/count(table1.id)) as per FROM table1 INNER JOIN table2 ON table1.id=table2.movieid WHERE userid=3 and table1.rate <> 0 GROUP BY userid
this will gives you what you need.
I suppose what you are looking for is:
SEELCT table1.id, table1.rate, table2.rating
FROM table1 INNER JOIN table2 ON table1.id=table2.movid
WHERE table1.rate>0 AND table2.userid=3
A simple INNER join plus filters in where clause to filter userid=3 and to show rates greater than zero
Following is not the best solution, but it should work:
select ROUND(sum(tmp.similarity_score)/max(tmp.cnt)) as Total_similarity_score
from
(
select t1.id,t1.rate,t2.movid,t2.rating,
(10 - abs(t1.rate-t2.rating))*10 as similarity_score,
(#cnt := #cnt +1) as cnt
from t1
inner join t2
on t2.movid = t1.id
cross join (select #cnt := 0)r
where userid = 3
and t1.rate <> 0
)tmp
;
Not sure if the title explains what I am trying to do correctly however I was unable to word it.
I am trying to create an output for a some graphs. The output I am aiming for is just the total value of some rows in a mySQL table grouped by a category ID. My tables are as follows:
Transactions:
TransactiondID | TransactionName |TransactionCategory| Value
*************************************************************
1 | GenericText1 | 1 | 30
2 | GenericText2 | 1 | 38
3 | GenericText2 | 2 | 38
And my Reference Data for TransactionCategory
TranCatID | TransCatName
*************************
1 | Tranportation
2 | Petrol
So what I want to do is do is a SUM of the value field by each category. So I would get an output of.
Category | Value
****************************
Transportation | 68
Petrol | 30
I got this but it does not work. I think it is completely incorrect but wanted to show my attempt.
SELECT SUM( `TransactionValue`) AS Value,
transaction_category.transaction_category
FROM Transactions
JOIN transaction_category on Transactions.TransactionID = transaction_category_id
Grouping by either "TransactionCategory" or "TranCatID" will give you the desired result shown as follows:
SELECT TransactionCategory.TransCatName, SUM( `Value`) AS Value FROM Transactions JOIN TransactionCategory on Transactions.TransactionCategory = TransactionCategory.TranCatID GROUP BY TransactionCategory.TransactionCategory;
or
SELECT TransactionCategory.TransCatName, SUM( `Value`) AS Value FROM Transactions JOIN TransactionCategory on Transactions.TransactionCategory = TransactionCategory.TranCatID GROUP BY TransactionCategory.TranCatID;
This should do the trick
SELECT TransactionCategory.TransCatName,
SUM(Transactions.Value) as Value
FROM Transactions
LEFT JOIN TransactionCategory ON TransactionCategory.TranCatID = Transaction.TransactionCategory
You can use this :
SELECT tc.TransCatName Category, SUM(t.Value) as Value
FROM TransactionCategory tc
LEFT JOIN Transactions t ON tc.TranCatID = t.TransactionCategory
group by tc.TransCatName
SQL HERE
OUTPUT
Category | Value
-----------------------
Petrol | 38
Transportation | 68
Please notice the SUM for PETROL, it should 38 as above, which is wrongly written 30 in your question description!
Hello I am trying to make a Select where the uses chooses department and would like to have clause WHERE this department is first, let's say we select 10 results from department: Taxes and then make a SUM SELECT of fee WHERE status = 1. Which results be selected based on the first select All the results are coming from the same table.
| id | department | status | fee |
----------------------------------
| 1 | tax | 1 | 20 |
| 2 | tax | 2 | 20 |
| 3 | tax | 1 | 20 |
| 4 | accounting | 1 | 20 |
So I would like to select if department is choose as tax, and status is 1 the sum of FEE columns which should be 40
So far my Select query looks like this:
SELECT P.id, P.fee, (SELECT SUM(P.fee) FROM cases P WHERE status = 1) as fee_USD
FROM cases P WHERE 1";
if (!empty($department)) { $sql .= " AND P.department = '$department'"; }
the last line is checking if department is given as select option. there are other options as well but to make it simple I have pasted only this part of it. Any help is welcome.
In the Current Selection Fee is = 80
You have to add correlation to your query:
SELECT P1.id, P1.fee,
(SELECT SUM(P2.fee)
FROM cases P2
WHERE P2.department = P1.department AND status = 1) as fee_USD
FROM cases P1
WHERE 1 ...
This way the subquery will return the SUM of only those records which are related to the current record of the main query.
I am using Symfony2 and doctrine to grab all the duplicate rows and how many times they appear. That part I have down. Now, each of these rows has a qty field as well. What I am wanting to do is run my query and show how many times the duplicate row appears as well as sum the qty field for each of these rows:
My database table looks like this:
id | sku | qty
----------------------
1 A 1
2 B 1
3 A 3
4 A 5
5 A 1
6 A 1
7 B 2
8 A 1
9 A 1
Here is my initial query that grabs all duplicate rows:
SELECT o, count(o.id) as cnt
FROM WIC\APIBundle\Entity\FBAOrderHistory o
GROUP BY o.sku HAVING cnt > 1 order by cnt desc
It outputs this:
id | sku | cnt
----------------------
1 A 7
2 B 2
But what I want is this:
id | sku | cnt | qty
----------------------
1 A 7 13
2 B 2 3
Does anyone know how to do this. Thanks so much in advance for your help!
Use SUM()
SELECT o, count(o.id) as cnt ,sum(o.qty) as
FROM WIC\APIBundle\Entity\FBAOrderHistory o
GROUP BY o.sku HAVING cnt > 1 order by cnt desc
Using DQL
Mysql Demo