Different between group by() and group by - mysql

when I use mysql I got this error and please can anybody explain me this. what is the different between A, B, C of the following?
A) select * from table where a=a group by(b) // this execute & work fine
B) select * from table where a=a group by b,c // this execute * work fine
c) select * from table where a=a group by (b,c) // this is giving an error - error is operand should contain 1 column.
In the A it works fine with out errors with brackets, but when I use the same method in C for multiple grouping its not working and gives mentioned error.
why is that? what is the different between group by () & group by in mysql grouping?
Thankyou.

These are equivalent:
group by (b), (c)
group by b, c
Because the brackets are redundant(they have no effect), but in this:
group by (b, c)
The brackets are creating a single ordering term from the expression b, c, which is not a single value, and order by terms must be single-valued.

group by (b,c) means you group by the field "b,c", because you use "()".
group by b,c means you group by the field b then group by field c

Related

Mysql: Sort an aggregate ascending with zeros last

I'm attempting to sort an aggregate column, which contains some zero values. I need the zero values to be last.
For non-aggregate columns I can do something like this (simplified example query):
SELECT age FROM books
ORDER BY
age = 0,
age ASC
However, for aggregate columns I'm getting an error as the column doesn't exist:
SELECT avg(age) as avg_age FROM books
GROUP BY book.type
ORDER BY
avg_age = 0,
avg_age ASC
The error is:
SQLSTATE[42S22]: Column not found: 1247 Reference 'avg_age' not supported (reference to group function)
I totally appreciate why this is happening, but I wasn't able to find a workaround, any tips?
There seams to be a (old) related bug report
[21 Mar 2016 9:22] Jiří Kavalík
Description: When using alias to aggregated column in ORDER BY only
plain alias is allowed, using it in any expression returns error.
http://sqlfiddle.com/#!9/e87bb/7
Workarounds:
- select the expression and use its alias
- use a derived table and order the outer one
How to repeat: create table t(a int);
-- these work select sum(a) x from t group by a order by x; select sum(a) x from t group by a order by sum(a); select sum(a) x from t
group by a order by -sum(a);
-- this one wrongly gives "Reference 'x' not supported (reference to group function)" select sum(a) x from t group by a order by -x;
source
You would have to write, this is better as the query is then also ANSI/ISO SQL standard valid meaning the query is most likely better portable between most databases vendor software.
SELECT
avg(books.age) as avg_age
FROM books
GROUP BY books.type
ORDER BY
avg(books.age) = 0
, avg(books.age) ASC
see demo this bug is fixed in MySQL 8.0 see demo
Try repeating the code
SELECT avg(age) as avg_age
FROM books
GROUP BY book.type
ORDER BY avg(age) = 0, avg(age) ASC

MySQL conditional concatenate based on multiple columns

I'm stumped on a proper query to get an output based on multiple columns and the conditions in those columns:
a b c
1 x x
2 x x
3 x
I would like the results to output, based on where the x's are in columns a, b and c:
1 a,c
2 a,b
3 a
Is this possible to do in mysql? Much appreciated
You can use the CONCAT_WS function (docs) and some IF statements.
SELECT tn.ID,
CONCAT_WS(
',',
IF(tn.a='x','a',null),
IF(tn.b='x','b',null),
IF(tn.c='x','c',null)
) as result
FROM TableName tn;
You can use IFNULL function for that (docs). For example:
SELECT a, IFNULL(b, c) FROM table_name;
It will select a for every case and conditionally b or c, depending on it's value (it have to be not null). But I'm afraid you cannot do more than that.

What is this SQL query syntax mean?

SELECT b.*,
( select a.USER_NAME
from A.db.USER a
where a.USER_ID=b.Booking_Inspector
) as USER_NAME
FROM A.dbo.Booking b
where b.Booking_Inspector=? and b.confirm=1
From this sql syntax, what is "," which after "*" mean?
and anyone can explain this query to me or tell me where I can start?
It means all the columns from table Booking, and to the far right (the last column per row) bring in the user_name column from table user relating on the user.user_id matching the booking.booking_inspector. Such that the Booking.confirm is 1, and Booking_inspector is filled in with a parameter passed.
So it limits the rows of output to confirm is 1 and Booking_Inspector is the parameter passed (or bound, etc) depending on the language calling it.
Select * means all columns. So all columns from the one table, and just one column from the other
In this case, (select a.USER_NAME from A.db.USER a where a.USER_ID=b.Booking_Inspector) is the subquery which will return column a.USER_NAME. So this query is selecting everything from b (b.*) and the column a.USER_NAME from the subquery. So like you put comma between column names in select query, it is same.
select all columns from b and one more column from that subquery as USER_NAME.
( select a.USER_NAME
from A.db.USER a
where a.USER_ID=b.Booking_Inspector
) as USER_NAME
That whole thing above as 1 column
SELECT b.*, [USER_NAME]
FROM A.dbo.Booking b
where b.Booking_Inspector=? and b.confirm=1

Does MySQL accept ORDER BY "nothing" LIMIT "all" when I only want to get number of results in a search query?

I have ported a search from Coldfusion into a MySQL stored procedure.
The actual search is run twice on the site. Once to get the number of records, the 2nd time to get the actual results to display.
So both MySQL syntax differ in the last two lines:
Get no of records:
SELECT COUNT(*) ...
GROUP BY a, b, c
HAVING ...
Actual results:
SELECT "rows"...
GROUP BY a, b, c
HAVING ...
ORDER BY var1, var2
LIMIT var_start, var_end
My question:
Since I need to run this twice, is there a way to at least use the same stored procedure = can I add default values to order/grouping "ORDER BY 'nothing' LIMIT 'all', and a parameter to the SELECT?
Sort of like an if statement
WHERE 1
AND IF( var_x = '', '.', var_x = some_value )
Thanks for input!
The first query is wrong - you shouldn't ask the MySQL engine to actually return the rows, and then count them, you should ask MySQL to count them directly:
SELECT COUNT(*)
FROM ...
GROUP BY a, b, c
HAVING ...
Trying to shoe-horn both record count and record retrieval in the same SQL statement or stored procedure is an unnecessary optimisation.
Why don't you use extra parameters with the use of count(*) if it's just the number of rows you want.
SELECT count(a) as number_of_a, count(b) as number_of b ...
GROUP BY a, b, c
HAVING ...
ORDER BY var1, var2
LIMIT var_start, var_end
Have you looked at sql_calc_found_rows?
select sql_calc_found_rows mytable.* ...

Interpreting a MySQL nested SELECT statement

I am not a MySQL expert by any means, but after reading the documentation for the SELECT statement, I did not find an answer to my problem.
I have this statement:
SELECT COUNT(*)=x.c FROM someTable,
(SELECT COUNT(*) c
FROM someTable
WHERE firstId <= secondId) x;
And I'm trying to figure out what the x.c means in the context of the query? Specifically, what is with the x that seems to be hanging out there?
I interpret the nested SELECT as SELECT COUNT(*) as c, making an alias for the row count as c, is that what the x is as well? What would it be an alias for?
Thanks!
The x is a table alias - a name for the nested SELECT statement in parentheses.
COUNT(*)=x.c
Is a boolean condition that the total row count of someTable be equal to the row count of someTable where firstId <= secondId
x.c is the column name for the count returned by the subquery.
They name the subquery "x" and in the subquery they name the count(*) "c". So "x.c" means the count returned by the subquery.
The x is an alias to the subquery - you will note that there is an x just after the subquery, denoting the alias name for it.
x is an alias for the table (SELECT COUNT(*) c FROM someTable WHERE firstId <= secondId).
MySQL requires that table subqueries have a unique alias. You'll notice there's an x at the end of the subquery, which makes the sub queries results appear as coming from table x.
In this case, x.c in the outer query means to refer to field c (the count result) in the aliased table x, which is the subquery.
X is an alias for joined someTable and the select you joined someTable with. I guess so :D
I guessed wrong, guys over me are right :P