Faster Active Record Query for counting a group? - ruby-on-rails

is there a more optimized way to count my records that have been grouped by a column? I just want to count all the records; i dont know why it appears i need to add a select statement before my group method.
User.select('username').group('username').to_a.count

The following will return a hash with username as the key and the count as the value:
User.group('username').count

Related

How to get the number of entries in a measurement

I am a newbie to influxdb. I just started to read the influx documentation.
I cant seem to get the equivalent of 'select count(*) from table' to work in influx db.
I have a measurement called cart:
time status cartid
1456116106077429261 0 A
1456116106090573178 0 B
1456116106095765618 0 C
1456116106101532429 0 D
but when I try to do
select count(cartid) from cart
I get the error
ERR: statement must have at least one field in select clause
I suppose cartId is a tag rather than a field value? count() currently can't be used on tag and time columns. So if your status is a non-tag column (a field), do the count on that.
EDIT:
Reference
This works as long as no field or tag exists with the name count:
SELECT SUM(count) FROM (SELECT *,count::INTEGER FROM MyMeasurement GROUP BY count FILL(1))
If it does use some other name for the count field. This works by first selecting all entries including an unpopulated field (count) then groups by the unpopulated field which does nothing but allows us to use the fill operator to assign 1 to each entry for count. Then we select the sum of the count fields in a super query. The result should look like this:
name: MyMeasurement
----------------
time sum
0 47799
It's a bit hacky but it's the only way to guarantee a count of all entries when no field exists that is always present in all entries.

Rails ActiveRecord Perform Group, Sum and Count in one query

I have two tables,
Order (ID, Value)
and
OrderType (ID, Name [Quote, Sale, Purchase, etc])
I want to get the total number of orders in each type (count) and the total value of those orders per type (sum)
I can get these individually using
Order.group(:order_type).count(:id)
and
Order.group(:order_type).sum(:value)
I would like to perform these in one query, the equivalent to the following SQL
SELECT
order_types.id, Count(*) as total_count, Sum(orders.value) As total_value
FROM
order
JOIN
order_types ON orders.order_type_id = order_types.ID
GROUP BY
order_types.id
The query should also return the full OrderType object so I can display the name in my view
Since ActiveRecord does not support multiple aggregation functions in the same query, you need to do a bit of raw SQL to achieve this.
grouped_sales = OrderType
.select('order_types.id, order_types.name,
sum(orders.value) as sale, count(*) as purchase')
.join('JOIN orders ON orders.order_type_id = order_types.id')
.group('order_types.id')
The point to note here is that you need to use an existing column in OrderType as the alias for your aggregated columns. Here you will get the OrderType object as well.
To access the result:
id -> grouped_sales.first.id
name -> grouped_sales.first.name
total orders -> grouped_sales.first.sale
order value -> grouped_sales.first.purchase
There is even better solution, just:
.pluck('sum(orders.value), count(*)').first
Nowadays pluck+arel will do the job.
model = Model.arel_table
Model.group(:order_type).pluck(model[:id].count, model[:value].sum)
Also appending with .order(:order_type) may be needed if there applied default ordering by ID.

Count strings in database table

I would like to know how to count choosed strings from database table. In one of my column are two strings called "correct" and "wrong". I have everything in array. I want to count how many strings called "correct" I have in column and how many called "wrong". I'm using sqlite.
You can try count(*) and a where.. something like:
SELECT Count(*) FROM yourTable WHERE yourColumn = 'wrong';
And another one to count the correct, or maybe you can subtract from the total.. I hope that helped!

Get a Rails record count without quering a 2nd time

I've got a Rails ActiveRecord query that find all the records where the name is some token.
records = Market.where("lower(name) = ?", name.downcase );
rec = records.first;
count = records.count;
The server shows that the calls for .first and .count were BOTH hitting the database.
←[1m←[35mCACHE (0.0ms)←[0m SELECT "markets".* FROM "markets" WHERE (lower(nam
e) = 'my market') LIMIT 1
←[1m←[36mCACHE (0.0ms)←[0m ←[1mSELECT COUNT(*) FROM "markets" WHERE (lower(na
me) = 'my market')←[0m
Why is it going to the database to get the count when it can use the results already queried?
I'm concerned about future performance. Today there are 1000 records. When that table holds 8 million rows, doing two queries one for data, and one for count, it will be expensive.
How do I get the count from the collection, not the database?
RactiveRecord use lazy query to fetch data from database. If you want to simple count the records, you can only call size of the retrun array.
records = Market.where("lower(name) = ?", name.downcase ).all
records.size
So, records is an ActiveRelation. You would think it's an array of all your Market records that match your where criteria, but it's not. Each time you reference something like first or count on that relation, it performs the query retrieve what you're asking for.
To get the actual records into an array, just add .all to the relation to actually retrieve them. Like:
records = Market.where("lower(name) = ?", name.downcase).all
count = records.count
For Rails 6.0.1 and Ruby 2.6.5
You will need to store the results into an array by using the to_a.
records = Market.where("lower(name) = ?", name.downcase).to_a
This will create the SQL query and store the results in the array records.
Then, when you call either records.first or records.count it will only return the data or do the calculation, not rerun a query. This is the same for records.size and records.length.
Another Example
I was needing to do this for a blog I am developing. I was trying to run a query to find all of the tags associated with a post, and I wanted to count how many tags there were. This was causing multiple queries until I came across the to_a suffix.
So, my SQL query looks like this:
#tags = TagMap.where(post_id: #post).joins(:tag).select(:id, '"tags"."name"').to_a
This looks through my TagMap table for all records that have post_id equal to the id of the post that I am viewing. It then joins to the Tags table and pulls only the id of the TagMap record and the name of the tag from the Tags table. Then it puts them all into an array. I can then run #tags.count and it will return the number of TagMap records for that post without doing another query.
I hope that this helps anyone using Rails 6+

Rails 3 Select Distinct Order By Number of Occurrences

In one of my models I have a country column. How would I go about selecting the top 3 countries based on how many models have that country?
Without any further information you can try this out:
YourModel.group('country').order('count_country DESC').limit(3).count('country')
when you call count on a field rails automatically adds an AS count_field_name field to your query.
Count must be called at the end of the query because it returns an ordered hash.

Resources