Count maximum times record appears in Database table - php

I am unable to find the proper mysql function but am trying to find the maximum number of a times a single record appears within a database relative to all other records.
For example:
ID | ....
================
1 | ....
2 | ....
2 | ....
2 | ....
3 | ....
3 | ....
the ideal return for what query i am trying to achieve is 3 (the count of 1 is 1, count of 2 is 3, count of 3 is 2 so return maximum count of ANY id).

Can't nest directly, otherwise you'll get a grouped max. Nest the selects instead.
select max(c) from (
select
count(*) c
group by
.. whatever ...
) x

SELECT MAX(MAX_COUNT) FROM (SELECT COUNT(COLUMN_NAME) AS MAX_COUNT FROM TABLE_NAME GROUP BY COLUMN_NAME)

Related

(MySQL) Group by field and select both COUNT(field) and number of grouped rows

I have a many-to-many table with approximately this structure:
id | obj
----+---------
1 | 27
1 | 42
2 | 32
2 | 42
2 | 162
2 | 89
3 | 2
3 | 209
Essentially the table associates any number of objects (obj) with any number of collections (id).
I am trying to SELECT from this table in a way that will return the number of rows in a GROUP BY clause grouping by id, and also the number of grouped rows grouped by the number of rows in each group.
If I simply do SELECT COUNT(id) FROM table GROUP BY id, I naturally get the following:
id | COUNT(id)
----+---------
1 | 2
2 | 4
3 | 2
That is, there is one row where COUNT(id) = 4 and there are two rows where COUNT(id) = 2. So far so good. But not what I’m looking for here.
What I need is this: for each distinct value returned by COUNT(id) (2 and 4 in this case), select both COUNT(id) and the number of rows that match that value in their COUNT(id) column (in this case 2 and 1, respectively: 2 rows have COUNT(id) = 2 and 1 row has COUNT(id) = 4).
In other words, from the table above, I would want this:
id_cnt | grp_cnt
-------+---------
2 | 2
4 | 1
– since grouping the table by id, you get two rows where COUNT(id) is 2 (ids 1 and 3); and one row where COUNT(id) is 4 (id 2).
Wrack my brain as I may, though, I cannot figure out a way to do this in one single query.
The closest I’ve been able to get to something that made sense in my head was this:
SELECT COUNT(*), id_cnt FROM table JOIN (SELECT COUNT(id) id_cnt FROM table GROUP BY id) a
– but that gives:
count(*) | id_cnt
---------+---------
21100 | 2
– which I admit confuses me a bit.
Can it be done?
(I find it odd that I can’t find this question already asked—surely this must have been asked before? Perhaps I’m just wording my search queries poorly…)
You can add another level of grouping around your first grouped query.
SELECT id_cnt, COUNT(*) AS grp_cnt
FROM (
SELECT COUNT(*) AS id_cnt
FROM test.test GROUP BY id) id_cnts
GROUP BY id_cnt;
You can get the cont by id this way
select id, count(*) as ctn
from table
group by id
and the count of same count with a second level count
select ctn, count(*)
from ( select id, count(*) as ctn
from table
group by id) t
group by ctn

Symfony2 Finding Duplicate Rows and Summing Another Column

I am using Symfony2 and doctrine to grab all the duplicate rows and how many times they appear. That part I have down. Now, each of these rows has a qty field as well. What I am wanting to do is run my query and show how many times the duplicate row appears as well as sum the qty field for each of these rows:
My database table looks like this:
id | sku | qty
----------------------
1 A 1
2 B 1
3 A 3
4 A 5
5 A 1
6 A 1
7 B 2
8 A 1
9 A 1
Here is my initial query that grabs all duplicate rows:
SELECT o, count(o.id) as cnt
FROM WIC\APIBundle\Entity\FBAOrderHistory o
GROUP BY o.sku HAVING cnt > 1 order by cnt desc
It outputs this:
id | sku | cnt
----------------------
1 A 7
2 B 2
But what I want is this:
id | sku | cnt | qty
----------------------
1 A 7 13
2 B 2 3
Does anyone know how to do this. Thanks so much in advance for your help!
Use SUM()
SELECT o, count(o.id) as cnt ,sum(o.qty) as
FROM WIC\APIBundle\Entity\FBAOrderHistory o
GROUP BY o.sku HAVING cnt > 1 order by cnt desc
Using DQL
Mysql Demo

SQL Counting and ordering by duplicate rows

I found another thread with this similar question but the query wasn't working for me for some reason or another.
I have a table like so:
id | 1 1 5 3 5
I need to use just SQL to echo out the most duplicated number
For instance, that would output:
id | 1 5 3 5
If that makes sense.
How would I achieve this?
Thank you so much
RETURNING JUST UNIQUE ID's
SELECT DISTINCT id FROM myTable
ID |
---------------
1 |
5 |
3 |
See DEMO
RETURNING JUST THE MOST DUPLICATED ID WITH COUNT
SELECT id, COUNT(id) AS Duplicates FROM test
GROUP BY id
ORDER BY Duplicates DESC
LIMIT 1;
ID | Duplicates
---------------
1 | 2
// without the LIMIT clause
ID | Duplicates
---------------
1 | 2
5 | 2
3 | 1
See DEMO
Or, as you see above, there may be TWO ID's that have been duplicated the same amount of times. You could do this, which would return both the highest duplicated ID's, if they're equal:
SELECT id, COUNT(id) AS Duplicates
FROM test
GROUP BY id
HAVING COUNT(id) = (
SELECT COUNT(id) AS great
FROM test
GROUP BY id
ORDER BY great DESC
LIMIT 1
)
ID | Duplicates
---------------
1 | 2
5 | 2
See DEMO
RETURNING JUST UNIQUE ID's IN PURE PHP
$results = // query
$results = array_unique($results);
Use a group by together with a count, like this:
select * from t group by id order by count(id) desc
And add a limit clause in order to get the single most duplicated value:
select * from t group by id order by count(id) desc limit 1

mysql speed of query - selecting max value of every 3 rows

I have a table that holds price information. I need to select the max value of every three rows. EXAMPLE:
Table `daily_high`
____ _______
| ID | HIGH |
| 1 | 24.65 |
| 2 | 24.93 |
| 3 | 26.02 |
| 4 | 25.33 |
| 5 | 25.16 |
| 6 | 25.91 |
| 7 | 26.05 |
| 8 | 28.13 |
| 9 | 27.07 |
|____|_______|
Desired output to new table (ID will be auto-increment so don't assume an association exists between this ID 1 and the daily_high ID 1:
____ ___________
| ID | 3MaxHIGH |
|____|___________|
| 1 | 26.02 |
| 2 | 25.91 |
| 3 | 28.13 |
|____|___________|
I want to compare IDs 1,2, and 3 to determine the high value among them. Then once I have compared 1-3, I want to move on to 4 through 6, then 7 through 9, etc until I've done this for all values contained in the table (currently about 400,000 values). I have written code that uses
SELECT max(HIGH) FROM daily_high as dh1 JOIN (SELECT max(HIGH) FROM daily_high WHERE id >= dh1 AND id < (dh1.id + 3))
This works but is horribly slow. I've tried using the SELECT statement where I identify the column values to be pull for display, meaning between the SELECT and FROM parts of the query.
I've tried to use JOIN to join all 3 rows onto the same table for comparison but it too is horribly slow. By slow I mean just under 10 seconds to gather information for 20 rows. This means that the query has analyzed 60 rows (20 groups of 3) in 9.65879893303 seconds (I didn't make this up, I used microtime() to calculate it.
Anyone have any suggestions for faster code than what I've got?
Keep in mind that my actual table is not the same as what I've posted above, but it the concept is the same.
Thanks for any help.
If you ID it continous you can make this
SELECT floor(id/3) as range, max(HIGH) FROM daily_high GROUP BY range;
Why not to use DIV operator for grouping your aggregation:
SELECT (id-1) DIV 3 + 1 AS ID, MAX(high) AS 3MaxHIGH
FROM daily_high
GROUP BY (id-1) DIV 3
This query gives the same result.
ID 3MaxHIGH
1 26.02
2 25.91
3 28.13
I was unable to run your query, and I believe that this one is faster.
UPD: To ensure that you have valid groups for your ranges, use this query:
select id, high, (id-1) div 3 + 1 from daily_high
result:
id high (id-1) div 3 + 1
1 24.65 1
2 24.93 1
3 26.02 1
4 25.33 2
5 25.16 2
6 25.91 2
7 26.05 3
8 28.13 3
9 27.07 3
Fuller answer with an example. The following code will do what I think you want.
SELECT FLOOR((row - 1) / 3), MAX(Sub1.high)
FROM (SELECT #row := #row + 1 as row, daily_high.*
FROM daily_high, (SELECT #row := 0) r) Sub1
GROUP BY FLOOR((row - 1) / 3)
ORDER BY Sub1.ID
The below query worked for me on a test table. perhaps not the best, but the other solutions failed on my test table.
This does require the ID's to be sequential. Also be sure to put an index on High aswell for speed.
SELECT FLOOR(T1.Id/3)+1 AS Id, ROUND(GREATEST(T1.High, T2.High, T3.High),2) AS High FROM `daily_high` T1, `daily_high` T2, `daily_high` T3
WHERE T2.Id=T1.Id+1
AND T3.Id=T2.Id+1
AND MOD(T1.Id, 3)=1
logic: if(id is divisible by 3, id/3-1, id/3)
select if(mod(id,3) = 0,floor(id/3)-1,floor(id/3)) as group_by_col , max(HIGH)
FROM daily_high GROUP BY group_by_col;

Sort by YES OR NO

I have search for Articles with dates. In MySQL is:
Article:
id | title
1 | first
2 | second
3 | third
4 | fourth
DatesArticle:
id | article_id | from | to
1 | 1 | 10-10-2010 | 11-11-2010
2 | 2 | 11-10-2010 | 12-12-2010
3 | 1 | 13-12-2010 | 12-01-2012
4 | 3 | 11-11-2012 | 12-12-2012
5 | 4 | 02-02-2013 | 02-02-2014
i would like get all Article with dates and sort this by availability.
for example i would like get all Articles and SORT this by dates FROM 12-10-2011 TO 12-01-2012
this should return me:
first (is in range FROM TO - DatesArticle.id = 3)
third (is in range FROM TO - DatesArticle.id = 4)
second (is NOT in range FROM TO)
fourth (is NOT in range FROM TO)
Is this possible with SQL or SQL and PHP? If yes, how?
Use the clause CASE, something like:
SELECT * FROM DatesArticle
ORDER BY CASE
WHEN id=3 AND CURRENT_DATE()<=from and to < CURRENT_DATE()>=to THEN 1
WHEN <condition_2> THEN 2
etc...
ELSE <any other condition>
END
Not saying the above is going to work as it is but it gives you and idea. If you add an example of the query you have tried or how are you building your where clause it would help for better answer.
My idea was to when it's id= 3 assign 1, if id = 4 assign 2, any other value assign 3, after that make the where condition and order by the number that you assign.
Try this:
select *,
case when t1.id=3 then 1 when t1.id=4 then 2 else 3 end as t
from article as t1
join DatesArticle as t2
on t1.id=t2.id
where CURRENT_DATE()<=from
and to < CURRENT_DATE()
order by t
You must first JOIN the tables in order to access article's data.
Then you ORDER on a logical condition (if there's a date within the given range).
SELECT title
FROM Article JOIN DatesArticle
ON (Article.id = DatesArticle.id)
ORDER BY DatesArticle.from > LastDate AND DatesArticle.to < FirstDate DESC;
(I never get ASC and DESC right in logical sorts -- try and see what happens)

Categories