Why am I only getting one result from the query below? The suggested "answer" has the first name "Susan" instead of what I got in my results.
SELECT EmpFirstName, EmpLastName, p.ProductName as ProductName,
YEAR(c.OrderDate) AS Year,
SUM(o.QuotedPrice + o.QuantityOrdered) AS TotalValue
FROM Employees
NATURAL JOIN Products p
NATURAL JOIN Order_Details o
NATURAL JOIN Orders c
ORDER BY Year, TotalValue DESC
Image of results
Image of Table Structure
Because there are a Sum in your Query
The result returned by the query does not match your expectations because the query is invalid. And your expectations are incorrect.
The presence of an aggregate (GROUP BY) function in the expression from the SELECT clause requires the presence of a GROUP BY clause. When such a clause does not exists, the SQL standard automatically adds a GROUP BY 1 clause that produces only one group from all the selected rows.
Each expression that appears in the SELECT clause of a GROUP BY query must follow one of these rules, in order to have a valid SQL query:
it also appears in the GROUP BY clause;
it's a call to an aggregate (GROUP BY) function;
is functionally dependent of one column that appears in the GROUP BY clause.
Because your query does not have a GROUP BY clause, the expressions EmpFirstName, EmpLastName, p.ProductName and YEAR(c.OrderDate) are not valid in the SELECT clause.
Before version 5.7.5, MySQL used to allow such invalid SQL queries but it reserved its privilege to return indeterminate values for the invalid expressions.
Since version 5.7.5, MySQL handles such queries correctly and rejects them. Other RDBMS-es handle them correctly since many years ago.
The explanation for the indeterminate values is simple: the JOIN and WHERE clauses extract some rows from the table(s). The (missing) GROUP BY clause produces only one record from all these rows. A GROUP BY query never returns rows from the table, it generates the values it puts in the result set. Since there are multiple different values for EmpFirstName in the group, the SQL standard says the query is invalid. MySQL used to ignore the standard but it had no valid rule about what value to pick from the EmpFirstName expression in the SELECT clause. Any value from the rows in the group is equally valid and that's what it returns: one random value from the group.
In order to get the results you expect you have to group the rows by OrderNumber and ProductNumber (and EmployeeID to get a valid SQL query):
Related
I'm using MySQL and I have the following table employees: table.
I had an exercise in which I had to select the oldest person. I know the correct way to do that is with a subquery: SELECT name, dob FROM employees WHERE dob = (SELECT MIN(dob) FROM employees).
However, I did it like so: SELECT name, dob FROM employees HAVING dob = MIN(dob). Now this returns an empty set, but doesn't throw any errors. So what does it do exactly? I've read that MySQL allows to refer to columns from SELECT clause in HAVING clause, without any GROUP BY clause. But why does it return an empty set?
When you use MAX (or other aggregate functions) in the select columns or the having clause, you cause an implicit GROUP BY () (that is, all rows are grouped together into a single result row).
And when grouping (whether all rows or with a specific GROUP BY), if you specify a column outside of an aggregate function (such as your dob =) that is not one of the things being aggregated on or something functionally dependent on it (for example, some other column in a table when you are grouping by the primary key for that table), one of two things will happen:
If you have enabled the ONLY_FULL_GROUP_BY sql_mode (which is the default in newer versions), you will receive an error:
In aggregated query without GROUP BY, expression ... contains nonaggregated column '...'; this is incompatible with sql_mode=only_full_group_by
If you have not enabled ONLY_FULL_GROUP_BY, a value from some arbitrary one of the grouped rows will be used. So it is possible your dob = MIN(dob) will be true (and it will definitely be true if all rows have the same dob), but you can't rely on it doing anything useful and should avoid doing this.
I have question about priority operation in sql statement. For example:
SELECT t1.c2, COUNT(DISTINCT t2.c1) as count_c1 FROM t1 JOIN t2
WHERE t2.c2 > 1 GROUP BY t1.c2 HAVING count_c1 > 1;
Which filter from this query will be applied first and which last. As I understand condition in HAVING will be last, it means that server generate full record set and after that remove all rows with count_c1 < 1 and return result to client.
Condition under WHERE will be first, it means that server don't even get rows with t2.c2 < 1, but what's about DISTINCT and GROUP BY? Result will be different if server will apply DISTINCT before GROUP BY from the opposite situation(GROUP BY first and DISTINCT second). I can't find anything in documentation about this, may be you help me.
Frist, like Thorsten Kettner said, your SQL syntax is actually invalid. Secondly,
The order of operations I was able to find (source) is as follows:
FROM clause (this includes JOIN's)
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause
The priority operation in SQL in as:
FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
You have learn about it in MVA here
The DBMS is free to either join first and then apply the WHERE clause or use the WHERE clause already to restrict rows to join.
Aggregation. Grouping by c2, counting distinct c1 in the process. You count distinct c1 per c2.
The HAVING clause (as it is dealing with the aggregated rows). MySQL allows for an alias name here, which doesn't comply with standard SQL (as the SELECT clause is not yet executed).
SELECT clause: Show the results.
I have two tables whome I am joining through left join. Both the tables are empty. But when I run the query, mysql returns a row with all NULLS.
I have tried several queries like
SELECT products.*,SUM(pq_quantity) as quantity
FROM `products` LEFT JOIN `products_quantities` ON `pq_product_idFk` = `p_id`
WHERE `p_volusion_id` = '37808'
OR
SELECT products.*,SUM(pq_quantity) as quantity
FROM `products` LEFT JOIN `products_quantities` ON `pq_product_idFk` = `p_id`
WHERE `p_volusion_id` = '37808' AND p_id IS NOT NULL
OR
SELECT products.*,SUM(pq_quantity) as quantity
FROM `products` LEFT JOIN `products_quantities` ON `pq_product_idFk` = `p_id` AND `p_volusion_id` = '37808' AND p_id IS NOT NULL
NONE of the above queries seem to work as I just want the result that is not NULL.
Thanks
Both the tables are empty. But when I run the query, mysql returns a row with all NULLS.
The presence of GROUP BY aggregate functions in the SELECT clause asks the GROUP BY clause to be present too. However, if it is not present, the SQL standard specifies that a single group is to be created using all the rows filtered by the WHERE clause.
Because of the * used in the SELECT clause, all the queries you posted are invalid SQL.
A query that contains a GROUP BY clause does not return rows from tables. It creates rows using the values extracted from the tables. First it creates groups (and sub-groups) using the expressions from the GROUP BY clause. All the rows from a group have the same value for the first expression specified in the GROUP BY clause.
If there are two or more expressions in the GROUP BY clause, each group is split into sub-groups using the second expression then each sub-group is further split into sub-sub-groups using the third expression (if exists) and so on.
From each such group of rows (after the last split), the database engine generates one new row and puts it into the result set. If the query contains in the SELECT clause expressions that are not either arguments of a GRUP BY aggregate function or also present in the GROUP BY clause then, most probably, these expressions will have more than one value in a subgroup. This is why the query is invalid SQL. Up to version 5.7.5, MySQL accepts such invalid queries but reserves itself the right to return any value it wants (from the group) for the offending expressions.
Back to your question, as explained above, even without having a GROUP BY clause, your query is processed as it had one and one group is created from all the rows filtered by the WHERE clause.
It is an empty group but this doesn't prevent the database engine to generate a row from it. Since there are no values to use to compute SUM(pG_quantity), NULL is the logical value it returns in the columns of the result set.
NULL is a special value that means the absence of any value or an unknown value. It make perfect sense in your case. You don't have any value in the tables, there is no way one could compute SUM(pq_quantity). Its value is not available (i.e. NULL).
Please consider the following query:
SELECT artist.id, COUNT(DISTINCT artist$styles.v_id)
FROM artist
LEFT JOIN artist$styles ON artist$styles.p_id = artist.id
This is the result I get:
id count
1 4
The questions are:
How come it's only selecting one row from the artist table, when there are 4 rows in it and there are no WHERE, HAVING, LIMIT or GROUP BY clauses applied to the query?
There are only three records in artist$styles having p_id of value 1, why is it counting 4?
Why if I add a GROUP BY clause to it I get the correct results?
SELECT artist.id, COUNT(DISTINCT artist$styles.v_id)
FROM artist
LEFT JOIN artist$styles ON artist$styles.p_id = artist.id
GROUP BY artist.id
----
id count
1 3
2 1
3 3
4 1
This all just doesn't make sense to me. Could this be a bug of MySQL? I'm running Community 5.5.25a
As stated in the manual page on aggregate functions (of which COUNT() is one):
If you use a group function in a statement containing no GROUP BY clause, it is equivalent to grouping on all rows.
As stated in the manual page on GROUP BY with hidden columns:
The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate.
In other words, the server has chosen one (indeterminate) value for column p_id, which happens in this case to be the value 1, whilst it has properly aggregated and counted the result for the COUNT() function.
Because you are then grouping on the correct columns, rather than on all rows.
It's not a bug; this behaviour is documented and by design.
It is a possible bug in Mysql. All non aggeregate columns should be included in Group by clause. MySQL does not force this and the result is unpredictable and hard to debug. As a rule always include all non-aggregate columns in the Group by clause. This is how all RDBMSs work
Count Function return single row result if you are not using group by clause and that's why its returning one row.
2.In your output
id count
1 4
4 is total no of results in that table not result for id 1.and it display in front of 1 because only one row produce.
3.when you use group by then a group of that column value is created that's why you get that output.
And finally its not a bug.Mysql provide a proper documentation for that you can read on mysql site.
I have a table named forms with the following structure-
GROUP | FORM | FILEPATH
====================================
SomeGroup | SomeForm1 | SomePath1
SomeGroup | SomeForm2 | SomePath2
------------------------------------
I use the following query-
SELECT * FROM forms GROUP BY 'GROUP'
It returns only the first row-
GROUP | FORM | FILEPATH
====================================
SomeGroup | SomeForm1 | SomePath1
------------------------------------
Shouldn't it return both (or all of it)? Or am I (possibly) wrong?
As the manual states:
In standard SQL, a query that includes a GROUP BY clause cannot refer to nonaggregated columns in the select list that are not named in the GROUP BY clause. For example, this query is illegal in standard SQL because the name column in the select list does not appear in the GROUP BY:
SELECT o.custid, c.name, MAX(o.payment)
FROM orders AS o, customers AS c
WHERE o.custid = c.custid
GROUP BY o.custid;
For the query to be legal, the name column must be omitted from the select list or named in the GROUP BY clause.
MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate.
In your case, MySQL is correctly performing the grouping operation, but (since you select all columns including those by which you are not grouping the query) gives you an indeterminate one record from each group.
It only returns one row, because the values of your GROUP column are the same ... that's basically how GROUP BY works.
Btw, when using GROUP BY it's good form to use aggregate functions for the other columns, such as COUNT(), MIN(), MAX(). In MySQL it usually returns the first row of each group if you just specify the column names; other databases will not like that though.
Your code:
SELECT * FROM forms GROUP BY 'GROUP'
isn't very "good" SQL, MySQL lets you get away with it and returns only one value for all columns not mentioned in the group by clause. Almost any other database would not perform this query. As a rule, any column, that is not part of the grouping condition must be used with an aggregate function.
as far as mysql is concerned, I just solved my problem by hit & trial.
I had the same problem 10 minutes ago. I was using mysql statement something like this:
SELECT * FROM forms GROUP BY 'ID'; // returns only one row
However using the statement like the following would yeild same result:
SELECT ID FROM forms GROUP BY 'ID'; // returns only one row
The following was my solution:
SELECT ID FROM forms GROUP BY ID; // returns more than one row (with one column of field "ID") grouped by ID
or
SELECT * FROM forms GROUP BY ID; // returns more than one row (with columns of all fields) grouped by ID
or
SELECT * FROM forms GROUP BY `ID`; // returns more than one row (with columns of all fields) grouped by ID
Lesson: Donot use semicolon, i believe it does a stringtype search with colons. Remove colons from column name and it will group by its value. However you can use backtick escapes eg. ID
Thank you everyone for pointing out the obvious mistake I was too blind to see. I finally replaced GROUP BY with ORDER BY and included a WHERE clause to get my desired result. That is what I was intending to use all along. Silly me.
My final query becomes this-
SELECT * FROM forms WHERE GROUP='SomeGroup' ORDER BY 'GROUP'
SELECT * FROM forms GROUP BY `GROUP`
it's strange that your query does work
The above result is kind of correct, but not quite.
All columns you select, which are not part of the GROUP BY statement have to be aggregated by some function (list of aggregation function from the MySQL docu). Most often they are used together with numeric columns.
Besides this, your query will return one output row for every (combination of) attributes in the columns referenced in the GROUP BY statement. In your case there is just one distinct value in the GROUP column, namely "SomeGroup", so the output will only contain one row for this value.
Group by clause should only be required if you have any group functions, say max, min, avg, sum, etc, applied in query expressions. Your query does not show any such functions. Meaning you actually not required a Group by clause. And if you still use such clause, you will receive only the first record from a grouped results.
Hence output on your query is perfect.
Query result is perfect; it will return only one row.