MySQL use generated column in select query - php

I have a MySQL query that runs a brief operation (totalling the counts in a select statement) and I want to use the result to do a math operation, but I'm getting an error.
Table:
id | group | count |
-----------------------------
1 1 3
2 1 2
Query:
select id, count,
(select sum(count) from table group by group) as total,
count/total as percent
from table
The error is because there is no real "total" column in the table. How can I make the query work?

You can save total as a variable, then use that in the division calculation.
SELECT
`id`, `count`,
#total:=(SELECT sum(`count`) FROM `table` GROUP BY `group`) AS `total`,
`count`/#total AS `percent`
FROM `table`
NOTE: GROUP is a reserved word in MySQL. You should enclose it (and all other field/table names) in backticks (`).

You can also do this without introducing a variable:
select id,
count,
(select sum(count) from `table` group by `group`) as total,
(select count/total) as percent
from `table`;
Produces:
+------+-------+-------+---------+
| id | count | total | percent |
+------+-------+-------+---------+
| 1 | 3 | 5 | 0.6000 |
| 2 | 2 | 5 | 0.4000 |
+------+-------+-------+---------+
2 rows in set (0.05 sec)

Your problem is that the inner query needs to generate 1 result per row, not 1 for every group. You want to add a where clause in the inner query saying something like
where inner_table.group = outer_table.group
so that only one result is returned.

group is a reserved word in mysql, as is table, you should use it like:
select id, count, (select sum(count) from `table` group by `group`) as total, count/total as percent from `table`
For more information: MySQL Reserved Words
You'll see there that you can actually use count but I would put all table and column names in quotes anyway.

This question already has an answer for MySql but by mistake if anyone lands here for MSSql as i did, it is as simple as below for MSSql
select id, count,
total = (select sum(count) from table group by group),
count/total as percent
from table

Related

MySQL - I need to SELECT the highest umber in a column when there are multiple ID's

Take the following dataset:
id | Number
1 | 6534
1 | 765
1 | 1234
2 | 744
2 | 6109
3 | 333
3 | 9888
3 | 3112
3 | 98432
I want to show the highest Number for each id.
So Like this:
id | Number
1 | 6534
2 | 6109
3 | 98432
How can I do this with a SELECT statement?
I've already tried the following:
SELECT * FROM mytable ORDER BY id, Number Desc
But this shows the entire dataset.
I'm not trying to get the number of occurences. I am trying to get the highest Number grouped by id but can't get it to work.
SELECT id, MAX(Number) as Number FROM mytable GROUP BY id
You can try :
Select id,max(Number) from Your_Table group by id
Your Query that you have tried, it will only order your Data table by the given parameters.
In the meantime, What i have proposed to you, will select the two columns you want to diplay (the id, and the maximum of the column "Number").
And the group by will help to the maximum of each group. That's why a group by id is the right clause to have the maximum of each group of Ids.
Most of time the id field is incremental but for your case you can use.
SELECT MAX(number) FROM `user` GROUP BY id
Where number is the column name from which you want to find MAX, and user is your table name.

How to Group by user_id and order by desc

Hello i am aware this is very basic but right now i am so confused i want to GROUP BY user_id ORDER BY id DESC LIMIT 4 (i have posted short example of table and my query)
My table looks like where id is auto increment i only save user_id i only want to take one user_id only once which is lastest entry in database ignore other.
Table
---------------------
id | user_id |
---------------------
13 | 25 |
12 | 36 |
11 | 25 |
10 | 42 |
9 | 95 |
8 | 25 |
7 | 95 |
---------------------
so on
I have tried this
SELECT * FROM `table` GROUP BY user_id ORDER BY `id` DESC LIMIT 4
I want it to output 25,36,42,95 i have also tried many experiments but nothing seems to be working.
Do i need timestamp or something to make it in group? or what query will work?
You are doing a partial GROUP BY which does not work the way you expect. Here is a query which produces the desired results:
SELECT MAX(id) AS MAXID, user_id
FROM `table`
GROUP BY user_id
ORDER BY MAXID DESC
LIMIT 4
The behavior is explained here:
MySQL extends the use of GROUP BY so that the select list can refer to
nonaggregated columns not named in the GROUP BY clause. [...] 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. Furthermore, the selection of values from each group
cannot be influenced by adding an ORDER BY clause. Sorting of the
result set occurs after values have been chosen, and ORDER BY does not
affect which values within each group the server chooses.
In your example you need to get result like 25,36,42,95, but sort by ID field.
If you will sort by it you will get different result.
You get a grouping in your query so you cannot use columns that not chosen in query (id is ommited there)
If you still need to order by id, i think that you need to add order by MAX('id') or MIN('id')
In your case i`ll make next query:
SELECT user_id FROM `table` GROUP BY user_id ORDER BY MAX(`id`) DESC LIMIT 4
Try this
SELECT MAX(id) as countid , `user_id` from `table`
GROUP BY `user_id`
ORDER BY countid DESC
LIMIT 20
In stead of grouping, you can use distinct, like below sql query.
SELECT distinct(user_id) FROM `table` ORDER BY `id` DESC LIMIT 4
SELECT * FROM (
SELECT 13 id, 25 UserID
UNION ALL
SELECT 12 id, 36 UserID
UNION ALL
SELECT 11 id, 25 UserID
UNION ALL
SELECT 10 id, 42 UserID
UNION ALL
SELECT 09 id, 95 UserID
UNION ALL
SELECT 08 id, 25 UserID
UNION ALL
SELECT 07 id, 95 UserID
) a
GROUP BY userid ORDER BY id DESC LIMIT 4

Count/Group By/Order By is only showing the count of the most common value and not the string itself

I'm querying a table to find the most common string in a column. However, it doens't seem to be working correctly. It should be returning the value of the most common string, but is instead returning the number of times the most common string exists. The query is:
SELECT COUNT(field_review_bar_tab_2_value) AS `Rows`
FROM (field_data_field_review_bar_tab_2)
GROUP BY (field_review_bar_tab_2_value)
ORDER BY `Rows` DESC
LIMIT 1
Table structure, simplified, would be something to the effect of:
-----------------------------------
| ID | field_review_bar_tab_2_value |
|----+----------------------------- |
| 1 | Food Drinks |
| 2 | Drinks |
| 3 | Food Drinks |
| 4 | Food |
-----------------------------------
The query is recognizing that, in the example above, "Food Drinks" is the most common string in the column. But, the query is returning "2" instead of "Food Drinks". Any ideas as to why it would be making the correct query but returning the count of the result instead of the value of the string?
You need to include field_review_bar_tab_2_value in the SELECT list as well. I've switched the aggregate to COUNT(*) here, and included the grouped column in the SELECT.
SELECT
field_review_bar_tab_2_value AS the_most_common_string,
COUNT(*) AS `Rows`
FROM (field_data_field_review_bar_tab_2)
GROUP BY (field_review_bar_tab_2_value)
ORDER BY `Rows` DESC
LIMIT 1
You're selecting the count, not the value. I think you mean:
SELECT field_review_bar_tab_2_value
FROM field_data_field_review_bar_tab_2
GROUP BY field_review_bar_tab_2_value
ORDER BY COUNT(*) DESC
LIMIT 1
Since you're already grouping by the value in question, you can just do COUNT(*)...
You will need to modify your query to return the field itself. Currently the query is only returning the COUNT because that's what is indicated in your select statement. Modify it as follows:
SELECT field_review_bar_tab_2_value AS `MostCommonString`, COUNT(field_review_bar_tab_2_value) AS `Rows`
FROM (field_data_field_review_bar_tab_2)
GROUP BY (field_review_bar_tab_2_value)
ORDER BY `Rows` DESC
LIMIT 1

Regular expression in MySQL / SQL?

i have for example:
tableAaa:
id | titleSSS
1 | sfdf
2 | sdfs
tableBbb:
id | titleUUU
1 | sfdf
2 | sdfs
tableCcc:
id | titleIII
1 | sfdf
2 | sdfs
etc, for example * 10.
Is possible make something like:
SELECT title* FROM table*
If yes, how?
EDIT: i dont want use UNION and do select from each table... These table is ~100. I would like make regular expression.
You can do it, but you'll have to list all column and table names manually:
SELECT titleSSS FROM tableAaa
UNION ALL
SELECT titleUUU FROM tableBbb
UNION ALL
SELECT titleIII FROM tableCcc
Note that you must use UNION ALL instead of UNION or otherwise you won't get duplicate rows in the output. Read more here: http://dev.mysql.com/doc/refman/5.0/en/union.html
The thing require by you is might not be possible you can do as below
SELECT title1 FROM table1
union
SELECT title2 FROM table2
union
SELECT title3 FROM table3
OR
You can make use of DynamicSQL to resolve your issue easily.
ans for you : How To have Dynamic SQL in MySQL Stored Procedure

How to count and limit record in a single query in MYSQL?

I am searching for records in a table as follows:
SELECT Id, Name FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;
Now, I am adding LIMIT to maintain my paging. But when user searches for word 'prashant' then total records I have is 124 for 'prashant'. But as the limit applied to the query so it only fetches 10 records in my PHP script and when I am count the mysql variable in PHP code it returns total records found is 10.
So basically I want to count and Limit using a single query, by making some modification in the above query, I want the total count (124) of records. I don't want to run a separate count(*) query for just counting the total result found by the query.
Thanks.
SELECT SQL_CALC_FOUND_ROWS
Id, Name
FROM my_table
WHERE
Name LIKE '%prashant%'
LIMIT 0, 10;
# Find total rows
SELECT FOUND_ROWS();
more info
MySQL supports doing this using SQL_CALC_FOUND_ROWS as mentioned by Ionut. However, it turns out that in many cases it's actually faster to do it the old fashioned way using two statements, where one of them is a regular count(). This does however require that the counting can be done using an index scan, which won't be the case for this very query, but I thought I'd mention it anyway.
This is for others with the same need (considering it's been 3 years from the time of this question).
I had a similar issue and I didn't want to create 2 queries. So what I did was to create an additional column for the total number and moved the LIMIT and OFFSET clauses at the end:
SELECT SQL_CALC_FOUND_ROWS * FROM (
SELECT `id`, `name`
FROM `my_table`
WHERE `name` LIKE '%prashant%'
) res,
(SELECT /*CEIL(FOUND_ROWS()/10) AS 'pages',*/ FOUND_ROWS() AS 'total') tot
LIMIT 0, 10
So the result is something like
| id | name | total |
+-----+----------------+-------+
| 1 | Jason Prashant | 124 |
| 2 | Bob Prashant | 124 |
| 3 | Sam Prashant | 124 |
| 4 | etc. prashant | 124 |
and I think this solution has no disadvantage in timing because it fetches the result only once, and then uses the already calculated row count for the additional column.
In case of huge tables and selecting multiple fields (not just Id, Name as in your example) i would recommend to use 2 queries. Selecting count(0) first with all those WHERE clauses and only then build the pagination, selecting data etc.
It will work really faster on some popular eCommerce website, for example.
Don't use SQL_CALC_FOUND_ROWS and FOUND_ROWS()
there are the bugs reported
here: https://bugs.mysql.com/bug.php?id=18454
and here: https://bugs.mysql.com/bug.php?id=19553
while on small tables BENCHMARK is dependent more on other things and the resulting time your SELECT will take will be roughly the same as COUNT(0) - SQL_CALC_FOUND_ROWS still puts restraints on LIMIT and ORDER BY database optimizations so if you depend on them don't use SQL_CALC_FOUND_ROWS
on large tables the BENCHMARK difference becomes huge where a COUNT(0) might take 0.003 sec the same SQL_CALC_FOUND_ROWS might now take 20 sec
By all metrices COUNT(0) is the superior choice
COUNT(0) SYNTAX:
(SELECT COUNT(0) FROM tableNames WHERE condition) AS alias
// alias is optional but needed if you need to use the result later
So your total query would look like this
(SELECT COUNT(0) FROM my_table WHERE name LIKE '%prashant%') AS countResults;
SELECT Id, Name FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;
And then just call countResults whereever you need it elsewhere...
Another advantage of using COUNT(0) is you can use it for searching both the same table as here or you can use it to search a different table...
So for instance if each person found also has 3, 2, 1, 5 diffenrent jobs respectively... you could just add a
(SELECT COUNT(0) FROM my_jobs_table WHERE name = name_row_in_jobs_table) AS jobs
inside your original SELECT like this
SELECT Id, Name (SELECT COUNT(0) FROM my_jobs_table WHERE name = name_row_in_jobs_table) AS jobs FROM my_table WHERE Name LIKE '%prashant%' LIMIT 0, 10;
Giving you:
--------------------
| id | Name | jobs |
--------------------
| 1 | Alice| 3 |
--------------------
| 2 | John | 2 |
--------------------
| 3 | Bob | 1 |
--------------------
| 4 | Jill | 5 |
--------------------
So when showing name[3] (ie. Bob) you could also show that Bob has 1 job by calling jobs[3]...

Categories