I have a problem to get SUM value from multiple table using join statement. The error is:
this is incompatible with sql_mode=only_full_group_by
Is it possible to get sum without change sql_mode? If possible, how to make a SQL statement to?
Table fuel:
vehicle_id | liter
-----------+-----------
2 | 43.5
4 | 78.3
8 | 20.5
Table usage:
date_usage | vehicle_id
-----------+-----------
2019-10-01 | 8
2019-10-15 | 2
2019-10-20 | 8
2019-10-20 | 4
2019-11-02 | 8
The SQL statement is below:
SELECT fuel.vehicle_id, SUM(fuel.liter), usage.date_usage
FROM fuel
LEFT JOIN usage ON fuel.vehicle_id = usage.vehicle_id
WHERE fuel.vehicle_id='8'
AND usage.date_usage >='2019-10-01' AND usage.date_usage <='2019-10-31'
GROUP BY fuel.vehicle_id
You have two possibilities to solve this:
Remove column usage.date_usage from SELECT.
Use a aggregate function on column usage.date_usage too:
MAX to get the highest value of the column.
MIN to get the lowest value of the column.
ANY_VALUE to get any value of the column.
So your query can look like the following (using MAX on column usage.date_usage):
SELECT fuel.vehicle_id, SUM(fuel.liter), MAX(`usage`.date_usage)
FROM fuel LEFT JOIN `usage` ON fuel.vehicle_id = `usage`.vehicle_id
WHERE fuel.vehicle_id = 8
AND `usage`.date_usage BETWEEN '2019-10-01' AND '2019-10-31'
GROUP BY fuel.vehicle_id
demo on dbfiddle.uk
Note: be careful using words like usage as identifiers (e.g. table and column names) in MySQL. There are keywords and reserved words you should avoid or quote with backticks.
Related
This is the SQL query I have written. It works until right before the group by statement but once I add that part, I get this error:
'reading_datetime' is neither present in the group by, nor is it an aggregate function. Add to group by or wrap in first() (or first_value) if you don't care which value you get
My query:
Select A.bill_account, hour(A.reading_datetime), A.reading_value
from (
Select cast(cast(bill_account as double) as int)bill_account, reading_datetime, cast(reading_value as double)reading_value, `interval`
from amerendataorc
WHERE cast(cast(`interval` as double)as int) = 3600 AND reading_datetime between '2015-03-15 00:00:00' and '2016-03-14 23:59:59'
) A
GROUP BY A.bill_account
HAVING (COUNT(A.bill_account)>= 8000) and (COUNT(A.bill_account) < 9500)")
Not sure exactly how the group by is messing up the query.
take the sum of reading date time and reading value
Select A.bill_account, sum(hour(A.reading_datetime)), sum(A.reading_value)
from (
Select cast(cast(bill_account as double) as int)bill_account, reading_datetime, cast(reading_value as double)reading_value, `interval`
from amerendataorc
WHERE cast(cast(`interval` as double)as int) = 3600 AND reading_datetime between '2015-03-15 00:00:00' and '2016-03-14 23:59:59'
) A
GROUP BY A.bill_account
HAVING (COUNT(A.bill_account)>= 8000) and (COUNT(A.bill_account) < 9500)")
---- explanation ------------
mysql> SELECT * FROM tt where user="user1";
+----------+-------+
| duration | user |
+----------+-------+
| 00:06:00 | user1 |
| 00:02:00 | user1 |
+----------+-------+
2 rows in set (0.00 sec)
mysql> SELECT * FROM tt where user="user1" group by user;
+----------+-------+
| duration | user |
+----------+-------+
| 00:06:00 | user1 |
+----------+-------+
1 row in set (0.00 sec)
once you add group by it will give only the summery after group by on that column in above example its giving 1st value
else you can get sum,max ... aggreagte values
SQL is trying to avoid an issue whereby you have multiple hour(A.reading_datetime) per A.Bill_Account. Grouping by Bill_account will give you a list of unique Bill_accounts. Then it has multiple hour(A.reading_datetime) per Bill_account and needs you to help it choose how to select one.
You need to group by each value that occurs or use aggregate functions on non-group by fields. If you group by reading_datetime and reading_value as well SQL will list all unique combinations of the three fields in the group by.
MySql suggests using first(); max() min() sum() etc are all aggregate functions what will help you get once value per Bill_account.
You will need to doing this for reading_value as well.
Standard SQL doesn't permit queries for which the select list refers to nonaggregated columns that are not named in the GROUP BY clause.
Therefore you have to add those columns to the GROUP BY clause, or you have to aggregate the columns in the SELECT clause, in your case:
Select A.bill_account, sum(hour(A.reading_datetime)), sum(A.reading_value)
But you have to evaluate if it is adequate for your data to sum those columns in that way, and if it isn't, add the columns as GROUP BY criteria.
Any field that is not included in the Group By Clause will require an aggregate function like SUM, COUNT, MIN or MAX to be included in the Selected fields.
http://www.w3schools.com/sql/sql_groupby.asp
To correct the issue you will need to use the following group by clause
GROUP BY A.bill_account, A.reading_datetime, A.reading_value
I want to find maximum value column in given table in MySql.
Table has following entry :
A | B | C | D
10 | 50 | 60 | 20|
Where A,B,C,D are column names and 10,50,60,20 are data points.
Expected output : C
select greatest(a,b,c,d)
from your_table
You can use if condition in select query.I will show the example for 3 columns in a table.
if condition syntax is as follows
if(condition,return value if true,return value if false)
This is the query
select if(col1>col2,if(col1>col3,col1,col3),if(col2>col3,col2,col3)) from your_table;
I want to return all rows that have a certain value in a column and have more than 5 instances in which a number is that certain value. For example, I would like to return all rows of the condition in which if the value in the column M has the number 1 in it and there are 5 or more instances of M having the number 1 in it, then it will return all rows with that condition.
select *
from tab
where M = 1
group by id --ID is the primary key of the table
having count(M) > 5;
EDIT: Here is my table:
id | M | price
--------+-------------+-------
1 | | 100
2 | 1 | 50
3 | 1 | 30
4 | 2 | 20
5 | 2 | 10
6 | 3 | 20
7 | 1 | 1
8 | 1 | 1
9 | 1 | 1
10 | 1 | 1
11 | 1 | 1
Originally I just want to insert into a trigger so that if the number of M = 1's is greater than 5, then I want to create an exception. The query I asked for would be inserted into the trigger. END EDIT.
But my table is always empty. Can anyone help me out? Thanks!
Try this :
select *
from tab
where M in (select M from tab where M = 1 group by M having count(id) > 5);
SQL Fiddle Demo
please try
select *,count(M) from table where M=1 group by id having count(M)>5
Since you group on your PK (which seems a futile excercise), you are counting per ID, whicg will indeed always return 1.
As i explain after this code, this query is NOT good, it is NOT the answer, and i also explain WHY. Please do not expect this query to run correctly!
select *
from tab
where M = 1
group by M
having count(*) > 5;
Like this, you group on what you are counting, which makes a lot more sense. At the same time, this will have unexpected behaviour, as you are selecting all kinds of columns that are not in the group by or in any aggregate. I know mySQL is lenient on that, but I don;t even want to know what it will produce.
Try indeed a subquery along these lines:
select *
from tab
where M in
(SELECT M
from tab
group by M
having count(*) > 5)
I've built a SQLFiddle demo (i used 'Test' as table name out of habit) accomplishing this (I don't have a mySQL at hand now to test it).
-- Made up a structure for testing
CREATE TABLE Test (
id INT NOT NULL AUTO_INCREMENT,
PRIMARY KEY(id),
M int
);
SELECT id, M FROM tab
WHERE M IN (
SELECT M
FROM Test
WHERE M = 1
GROUP BY M
HAVING COUNT(M) > 5
)
The sub-query is a common "find the duplicates" kind of query, with the added condition of a specific value for the column M, also stating that there must be at least 5 dupes.
It will spit out a series of values of M which you can use to query the table against, ending with the rows you need.
You shouldn't use SELECT * , it's a bad practice in general: don't retrieve data you aren't actually using, and if you are using it then take the little time needed to type in a list of field, you'll likely see faster querying and on the other hand the code will be way more readable.
I have two simple Mysql tables:
SYMBOL
| id | symbol |
(INT(primary) - varchar)
PRICE
| id | id_symbol | date | price |
(INT(primary), INT(index), date, double)
I have to pass two symbols to get something like:
DATE A B
2001-01-01 | 100.25 | 25.26
2001-01-02 | 100.23 | 25.25
2001-01-03 | 100.24 | 25.24
2001-01-04 | 100.25 | 25.26
2001-01-05 | 100.26 | 25.28
2001-01-06 | 100.27 | 30.29
Where A and B are the symbols i need to search and the date is the date of the prices. (because i need the same date to compare symbol)
If one symbol doesn't have a date that has the other I have to jump it. I only need to retrive the last N prices of those symbols.
ORDER: from the earliest date to latest (example the last 100 prices of both)
How could I implement this query?
Thank you
Implementing these steps should bring you the desired result:
Get dates and prices for symbol A. (Inner join PRICE with SYMBOL to obtain the necessary rows.)
Similarly get dates and prices for symbol B.
Inner join the two result sets on the date column and pull the price from the first result set as the A column and the other one as B.
This should be simple if you know how to join tables.
I think you should update your question to resolve any of the mistakes you made in representing your data. I'm having a hard time following the details. However, I think based on what I am seeing there are four MySQL concepts you need to solve your problem.
The first is JOINS you would use a join to put two tables together so you may select related data using the key that you describe as "id_symbol"
The second would be to use LIMIT which will allow you to specify the number of records to return such as that if you wanted one record you would use the keywould LIMIT 1 or if you wanted a hundred records LIMIT 100
The third would be to use a WHERE clause to allow you to search for a specific value in one of your fields from the table you are querying.
The last is the ORDER BY which will allow you to specify a field to sort your returned records and the direction you want them sorted ASC or DESC
An Example:
SELECT *
FROM table1
JOIN table2 ON table1.id = table2.table1_id
WHERE table1.searchfield = 'search string'
LIMIT 100
ORDER BY table1.orderfield DESC
(This is pseudo code so this query may not actually work but is close and should provide you with the correct idea.)
I suggest referencing the MySQL documentation found here it should provide everything you need to keep going.
Let's say we have this table:
Symbol | Size
A | 12
B | 5
A | 3
A | 6
B | 8
And we want a view like this:
Symbol | Size
A | 21
B | 13
So we use this:
Select Symbol, sum(Size) from table group by Symbol order by Symbol ASC
But instead we get this:
Symbol | Size
A | 12
B | 5
What am I doing wrong?!
You are doing it right, you should expect the correct results. Could you please supply more information about the DB you are using, additional schemas, etc?
Maybe you have some unique index on Symbol?
Try to execute the following to "sanity-test" your system:
SELECT SUM(Size) FROM table
Should result in 34
SELECT Symbol, Count(*) FROM table GROUP BY Symbol
Should results in 3 and 2
If both of the above work perfectly as you noted, please try:
SELECT Symbol, Count(*), Sum(Size) FROM table GROUP BY Symbol
This is your code, with the additions of Count(*) and without the ORDER BY clause. If that does not work after the two above do, I'm really puzzled...
I found out that somewhere in the Select commands that leaded to the Un-SUMable table instead of a left join there was a simple join.Although I still don't get why that should mess up the calculation, I changed that and now it works... I'm sorry I couldn't upload the whole thing...