How to get distinct rowcount using ActiveJdbc? - activejdbc

How do we get distinct rowcount in activejdbc? I tried many different variations but none of them worked
Tablename.count("?", "distinct id")
Tablename.count("distinct ?", "id") //missing expression
Base.exec("select count(distinct id) from tablename") //return 1 always (probably the count)

You are using the wrong API. Since you are selecting, you need to use any one of the Base.find... methods, not Base.exec, which is for INSERT/UPDATE/DELETE.

Related

Rails/SQL - How to filter by distinct value in a group

I'm working in Rails, but an answer in SQL is equally helpful. Let's say I have a table of Users and a table of Purchases. I want to find the Users who have only ever bought Item A. I was hoping to use a query along the lines of:
User.joins(:purchases).group(:id).having("DISTINCT(item) = 'A'").pluck(:id)
This is a simplification of the question I need to answer, but this grouping issue is my main roadblock. For that reason, I'm hoping for an answer that is logically very similar, as other workarounds would likely not apply.
Does this work in Rails?
User.joins(:purchases).group(:id).having("MIN(item) = MAX(item) AND MIN(item) = 'A'").pluck(:id)
This phrase as: there is only one distinct value (since MIN() and MAX() are equal), that is 'A'.
Alternatively:
having("MAX(CASE WHEN item <> 'A' THEN 1 ELSE 0 END) = 0")
Which would stand for: no other value than 'A'.
In having you can use only aggregate functions (e.g. having count(id) > 2) or expressions on columns you did the grouping on e.g. having("id > 1").
So depending on your db you may try to find an aggregate function that identifies existence of item in the grouping per id.
For PostgreSql that would be something like (haven't tested):
...
GROUP BY id
HAVING 'A' = ANY(ARRAY_AGG(item))

Rails: Need to scope by max version

I have this problem, I've got database table that looks like this:
"63";"CLINICAL...";"Please...";Blah...;"2014-09-23 13:15:59";37;8
"64";"CLINICAL...";"Please...";Blah...;"2014-09-23 13:22:51";37;9
The values that matter are the second to last and last one.
As you can see, the second to last (abstract_category_numbers) are the same, but the last differs (version_numbers)
Here is the problem:
When I make a scope, it returns all of the records, which i need to focus on the one with the maximum version number.
In SQL i would do something like this:
'SELECT * FROM Category c WHERE
NOT EXISTS SELECT * FROM Category c1
WHERE c.version_number < c1.version_number
AND c.abstract_category_id = c1.abstract_category_id'
But i'm totally lost at Ruby, more specifically how to do this kind of select in the scope (I understand it should be a relation)
Thanks
We can create a scope to select the category with max version_number like this:
scope :with_max_version_number, -> {
joins("JOIN ( SELECT abstract_category_id, max(version_number) AS max_version
FROM categories
GROUP BY abstract_category_id
) AS temp
ON temp.abstract_category_id = categories.abstract_category_id
AND temp.max_version = categories.version_number"
)
}
Basically, we will select the category with the max_version value on temp table in the subquery.
Btw, I expect the table name is categories, you may correct it. Then the final query will be:
Category.with_max_version_number
Scopes are suppose to return an array of values even if there is only 1 record.
If you want to ALWAYS return 1 value, use a static method instead.
def self.max_abstract_category
<your_scope>.max_by{ |obj| obj.version_number }
end
If I understand your question: you have a database table with a version_number column, which rails represents using an Active Record model--that I'll call Category because I don't know what you've called it--and you want to find the single Category record with the largest version_number?
Category.all.order(version_numbers: :DESC).limit(1).first
This query asks for all Category records ordered by version_number from highest to lowest and limits the request to one record (the first record, a.k.a the highest). Because the result of this request is an array containing one record, we call .first on the request to simply return the record.
As far as I'm aware, a scope is simply a named query (I don't actually use scopes). I think you can save this query as a scope by adding the following to your Category model. This rails guide explains more about Scopes.
scope :highest_version, -> { all.order(version_numbers: :DESC).limit(1).first }
I join implementation with baby_squeel but for some reason it was very slow on mysql. So I ended up with something like:
scope :only_latest, -> do
where(%{
NOT EXISTS (SELECT * FROM Category c
WHERE categories.version_number < version_number
AND categories.abstract_category_id = abstract_category_id')
}
end
I filed a BabySqueel bug as I spent a long time trying to do in a code proper way to no avail.

Sort by SQL Count Used in WHERE Clause in ActiveRecord Scope

I'm trying to get a calculated column used during a scope declaration "where" clause passed on so that it is then useable in the returned set. I've tried this many different ways, and none work. Ultimately, what I am trying to accomplish is to ORDER the returned set by that count. Here is my scope so far:
scope :used_in_past, ->(days_ago) {
where('(SELECT count(*) as total_tasks FROM grouptask WHERE creatorstudentid = sid AND creationdate > ?) > 0', Date.today-days_ago)
}
I'd like to "ORDER BY" total_tasks, and also hopefully pass it on to be used in a view. Whenever I try to use that named column it just says it doesn't exist, though.
Maybe in the SQL sentence you could do that, with Alias or Function
SELECT COUNT(sid) AS total_tasks
FROM grouptask
WHERE creatorstudentid = sid AND creationdate>0
GROUP BY sid
ORDER BY COUNT(sid);
I didn't see in your statement the GROUP BY section if you are using Aggregation Function Maybe you required
I hope this answer could help you
Regards

VB LINQ: Order By doesn't work when used with Distinct

I know this is supposed to be a solved issue but I cannot get the documented solutions to work for me. The code below is suppose to do the order by after the distinct but it does not. I referred to this post: LINQ to SQL does not generate ORDER BY when DISTINCT is used?
fyMonth = (From f In DbContext.FYMonth
Select f.Month).Distinct().OrderBy(Function(n) n).ToList()
I get an error when I try:
OrderBy(Function(n) n.SortOrder)
Any ideas?
Your query is selecting months and you're getting the distinct months. A month does not contain a SortOrder property, you no longer have access to that property on your FYMonth objects. You'll need to include the SortOrder into your projection, distinct then sort it, then project back to the month.
fyMonth = DbContext.FYMonth
.Select(Function(x) New With { x.Month, x.SortOrder })
.Distinct
.OrderBy(Function(x) x.SortOrder)
.Select(Function(x) x.Month)
This assumes that the SortOrder for each month will be the same across all months.

NHibernate How to Select distinct objects based on specific property using HQL?

How can HQL be used to select specific objects that meet a certain criteria?
We've tried the following to generate a list of top ten subscribed RSS feeds (where SubscriptionCount is a derived property):
var topTen = UoW.Session.CreateQuery( #"SELECT distinct rss
FROM RssFeedSubscription rss
group by rss.FeedUrl
order by rss.SubscriptionCount DESC
")
.SetMaxResults(10)
.List<RssFeedSubscription>();
Where the intention is only to select the two unique feed URLs in the database, rather than the ten rows int the database instantiated as objects. The result of the above is:
Column 'RssSubscriptions.Id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
It's possible just to thin out the results so that we take out the two unique feed URLs after we get the data back from the database, but there must be a way to do this at the DB level using HQL?
EDIT: We realise it's possible to do a Scalar query and then manually pull out values, but is there not a way of simply specifying a match criteria for objects pulled back?
If you change your HQL a bit to look like that:
var topTen = UoW.Session.CreateQuery( #"SELECT distinct rss.FeedUrl
FROM RssFeedSubscription rss
group by rss.FeedUrl
order by rss.SubscriptionCount DESC
")
.SetMaxResults(10)
.List();
the topTen variable will be an object[] with 2 elements in there being the 2 feed URLs.
You can have this returned as strongly typed collection if you use the SetResultTransformer() method of the IQuery interfase.
You need to perform a scalar query. Here is an example from the NHibernate docs:
IEnumerable results = sess.Enumerable(
"select cat.Color, min(cat.Birthdate), count(cat) from Cat cat " +
"group by cat.Color"
);
foreach ( object[] row in results )
{
Color type = (Color) row[0];
DateTime oldest = (DateTime) row[1];
int count = (int) row[2];
.....
}
It's the group by rss.FeedUrl that's causing you the problem. It doesn't look like you need it since you're selecting the entities themselves. Remove that and I think you'll be good.
EDIT - My apologies I didn't notice the part about the "derived property". By that I assume you mean it's not a Hibernate-mapped property and, thus doesn't actually have a column in the table? That would explain the second error message you received in your query. You may need to remove the "order by" clause as well and do your sorting in Java if that's the case.