Count distinct elements and return only one - mysql

I have a table with many integers in column named 'data'
data | param
123 1
432 1
123 1
423 2
234 1
423 2
I have a query
SELECT data FROM data_table WHERE param=*something* GROUP BY data
ORDER BY rand() LIMIT 1
That returns a random distinct integer from the table. But I also need to get the total number of integers that I was choosing from. I tried:
SELECT DISTINCT(data) AS data, COUNT(DISTINCT(data)) as count FROM
data_table WHERE param=*something* ORDER BY rand() LIMIT 1
This returns correct number from which data was chosen, but the data returned is no random - it is always the same row. So I need to get number of rows that rand() were selected after WHERE was applied. So making a query on above table should return:
query WHERE param='1':
data count
123 3
query WHERE param='1':
data count
432 3
query WHERE param='1':
data count
234 3
query WHERE param='2':
data count
423 1

This works. I normally don't recommend putting a query in the selector because it evaluates for each row returned. However in this case you are only returning one row so it is OK.
select
count(distinct data) as cnt,
(SELECT data FROM data_table GROUP BY data
WHERE param='xxx'
ORDER BY rand() LIMIT 1) as random
from data_table
WHERE param='xxx'
See this SQL Fiddle to see it work without the where statements.

I think this situation needs to be split in two steps:
Select the random entry where param has the value you want
Count the entries of the data
I propose this solution
set #yourParam = 1; -- Put here the parameter value you want to filter
select
data,
(select count(distinct date) from data_table where param=#yourParam) as `count`
from
data_table
where
param = #yourParam
order by
rand()
limit 1;
Hope this helps you

try this
select
data, (select count(distinct data) from data_table where param=1) as `count`
from
data_table where param = 1
order by rand()
limit 1
DEMO HERE

I think the easiest is to join another select statement to get the total number of rows and add that to your main SELECT statement.
SELECT data AS data, count.count
FROM data
JOIN (SELECT COUNT(DISTINCT(data)) AS count FROM data WHERE parameter = "test") AS count
WHERE parameter = "test"
ORDER BY rand()
LIMIT 1;
Here's a SQL Fiddle

Related

Random row from random derived table

I've a set of tables and I want to select a random row from within a random one of the tables.
If there's 5 tables
Table1
Table2
Table3
Table4
Table5
Each has the same data format.
I've tried the below, the first part in selecting a random table works but grabbing the info from the table is returning 0 rows.
SELECT * FROM (SELECT `cat_table_name` from `category-defines` GROUP BY `cat_table_name` LIMIT 1) AS x ORDER BY RAND() LIMIT 3
Not every task can be done in a single SQL query.
In SQL, all table names (really, all identifiers) must be fixed at the time the query is parsed. You can't write an SQL query that makes choices of tables (or columns, etc.) based on expressions evaluated during the query.
By analogy: it would be like in any other code, trying to call a function whose name is based on the return value of the function you want to call.
So you can't do what you want in one query.
You could pick the random table name in one query, then use that result as you form the next query.
SELECT `cat_table_name` from `category-defines` GROUP BY `cat_table_name` LIMIT 1
SELECT * FROM `$result_from_previous_query` ORDER BY RAND() LIMIT 3
That's the simplest solution.
Be sure to delimit your table name in back-ticks, just in case one of the table names is FROM or some other reserved keyword.
(Note: the first query above doesn't pick a random table name, it always picks the first table).
A comment above suggests a UNION of all the tables. This is what that would look like:
SELECT *
FROM
(SELECT FLOOR(RAND()*5)+1 AS table_num) AS r
JOIN (
(SELECT 1 AS table_num, * FROM my_table1 ORDER BY RAND() LIMIT 3)
UNION
(SELECT 2 AS table_num, * FROM my_table2 ORDER BY RAND() LIMIT 3)
UNION
(SELECT 3 AS table_num, * FROM my_table3 ORDER BY RAND() LIMIT 3)
UNION
(SELECT 4 AS table_num, * FROM my_table4 ORDER BY RAND() LIMIT 3)
UNION
(SELECT 5 AS table_num, * FROM my_table5 ORDER BY RAND() LIMIT 3)
) AS x USING (table_num)
But this has at least two problems:
It bears the performance cost of picking random rows from every table, just to throw away most of them. Wasteful.
You still have to know the table names in advance, so if they aren't fixed, you end up running another query before this one to get the list of table names.
That is because the main query will be executed on the result of the derived table (in this case the table name), not the actual table name.
As far as my MySQL knowledge stretches you have to split this into two queries, where the first query retrieves the table name and the second query uses the result from the first query. In PHP it would look something like this
//get a random table name
$stmt = $this->pdo->prepare('SELECT `cat_table_name` as table from `category-defines` GROUP BY `cat_table_name` LIMIT 1');
$stmt->execute();
$row = $stmt->fetch(PDO::FETCH_ASSOC);
//select 3 random rows with the table name
$stmt = $this->pdo->prepare('SELECT * FROM '.$row['table'].' ORDER BY RAND() LIMIT 3');
$stmt->execute();
$randomRows = $stmt->fetchAll(PDO::FETCH_ASSOC); //the three random rows

Mysql SELECT function inside mysql LIMIT function

SELECT COUNT('2018-02-12')
as ids FROM tg_partner_data
WHERE assign_to = '2'
AND
followup_date = '2018-02-12' AND active='Y'
LIMIT (SELECT count FROM tg_master_count WHERE count_for = 'followup')
I tried to get count as output but this query doesnot works . I am using like this because the limit setting is dynamic.
An immediate problem with your use of LIMIT is that you have no ORDER BY clause. Which first records do you expect from the result set? This is not clear. I will give a generic pattern which you can use to have a subquery limit the number of records.
Consider a simple table with just one column:
col
1
2
3
4
5
Now let's say that you want to limit the number of records in the result set, based on an ordering of col, using some subquery. We can write the following:
SET #rn=0;
SELECT col
FROM
(
SELECT
col,
#rn:=#rn+1 rn
FROM yourTable
ORDER BY
col
) t
WHERE t.rn <= (SELECT 3 FROM dual); -- replace with your own subquery
Demo
The basic idea here is that we simulate row number in a subquery, that is, we assign a row number to each record, ordered according the the col column. Then we subquery that table, and retain only records matching the subquery you want to use to limit.

Mysql count ignores group by

I try to count rows from a group by result.
I want to count the number of exercise where there muscle is 1
My problem is that the count ignores the group by.
I want to use this:
SELECT COUNT(id) FROM soFitTest.users_program
where user_name = 1127 AND muscle = 1
group by exercise;
In my count I get 3, but when I run the query without this count I get only 1 row.
See the attached image.
If you are just trying to count the rows, then try " count(*) ", instead of specifying "id" in count function.
SELECT COUNT(*) FROM soFitTest.users_program where user_name = 1127 AND muscle = 1;
Hope this helps.
The first query from your image is invalid according to the SQL standard:
SELECT *
FROM soFitTest.users_program
WHERE user_name = 1127 AND muscle = 1
GROUP BY exercise
It happens that MySQL accepts it and produces a result but the values it returns are not determined. It is explained in the documentation page about how MYSQL handles GROUP BY.
The same query could produce a different result if the rows in the table are stored in a different order on the physical storage.
You should run:
SELECT *
FROM soFitTest.users_program
WHERE user_name = 1127 AND muscle = 1
i.e. without GROUP BY to see what rows match the conditions, before being aggregate by GROUP BY.
Then, when you the add GROUP BY clause, put in the SELECT clause only:
columns that appear in the GROUP BY clause - exercise for example;
GROUP BYaggregate functions - they combine the values from all the rows in a group to produce a single value; COUNT(*) for example will count the number of rows in each group;
you can add columns that are functionally-dependent on columns that appear in the GROUP BY clause; in plain English this means that if exercise is the PK of table users_program then you can use any other column of that table because its value is determined by the value of column exercise; but this is only if exercise is the PK (which is probably not the case here).
In conclusion, the query you probably want is:
SELECT exercise, COUNT(*)
FROM soFitTest.users_program
WHERE user_name = 1127 AND muscle = 1
GROUP BY exercise
It filters the rows that have user_name = 1127 AND muscle = 1 then makes groups out of them. Each group contains all the rows that have the same value in column exercise. From each group it produces a single row into the returned result set. The row contains the value of column exercise (which is the same for all rows in the group) and the number of rows in the group (COUNT(*)).
If you want to get count of exercices, your query is correct:
SELECT COUNT(1) FROM soFitTest.users_program where user_name = 1127 AND muscle = 1;
(COUNT(1) gives same result as COUNT(*) but doesn't try to retrieve all fields from DB - it's more efficient)
And if you need to get all rows with those criteria, you must skip GROUP BY:
SELECT * FROM soFitTest.users_program where user_name = 1127 AND muscle = 1
How about this:
SELECT COUNT(DISTINCT(exercise)) FROM ......
The answer is :
SELECT COUNT(t1.id) FROM
(SELECT id FROM soFitTest.users_program
where user_name = 1127 AND muscle = 1 group by exercise) t1;

Determine total amount of top result returned

I would like to determine two things from a single query:
Most prevalent column in a table
The amount of times such column was located upon querying the table
Example Table:
user_id some_field
1 data
2 data
1 data
The above would return user_id # 1 as being the most prevalent in the table, and it would return (2) for the total amount of times that it was located in the table.
I have done my research and I came across two types of queries.
GROUP BY user_id ORDER BY COUNT(*) DESC
SUM
The problem is that I can't figure out how to use these two queries in conjunction with one another. For example, consider the following query which successfully returns the most prevalent column.
$top_user = "SELECT user_id FROM table_name GROUP BY user_id ORDER BY COUNT(*) DESC";
The above query returns "1" based on the example table shown above. Now, I would like to be able to return "2" for the total amount of times the user_id (1) was found in the table.
Is this by any chance possible?
Thanks,
Evan
You can include count(*) in the SELECT list:
SELECT user_id, count(*) as totaltimes from table_name
GROUP BY user_id ORDER BY count(*) DESC;
If you want only the first one:
SELECT user_id, count(*) as totaltimes from table_name
GROUP BY user_id ORDER BY count(*) DESC LIMIT 1;

mysql random rows

how to form a query to select 'm' rows randomly from a query result which has 'n' rows.
for ex; 5 rows from a query result which has 50 rows
i try like as follows but it errors
select * from (select * from emp where alphabet='A' order by sal desc) order by rand() limit 5;
u can wonder that why he needs sub query, i need 5 different names from a set of top 50 resulted by inner query.
SELECT * FROM t
ORDER BY RAND() LIMIT 5
or from your query result:
SELECT * FROM ( SELECT * FROM t WHERE x=y ) tt
ORDER BY RAND() LIMIT 5
This will give you the number to use as 'm' (limit)
TRUNCATE((RAND()*50),0);
...substitute 50 with n.
To check it try the following:
SELECT TRUNCATE((RAND()*50),0);
I should warn that this could return 0 as a result, is this ok for you?
For example you could do something like this:
SELECT COUNT(*) FROM YOUR_TABLE
...and store the result in a variable named totalRows for example. Then you could do:
SELECT * FROM YOUR_TABLE LIMIT TRUNCATE((RAND()*?),0);
where you substitute the '?' with the totalRows variable, according to the tech stack you are using.
Is it clearer now? If not please add more information to your question.