Using CodeIgniter's Active Record class and MySQL, I have a table of posts with user_id and various other fields, and I want to count how many posts each user has made. I could get rows where user_id = $whatever and count the number of results, but I'd have to loop through every user_id and use that count_all_results() query over and over for each one.
There must be a better way! If every field just had a field with a 1 in it, I could select_sum up that field and get a count. But that seems dumb.
Many thanks in advance!
Using active record should be:
$this->db->select('field1, ... ,fieldn, count(1) as number_elements_of_row');
$this->db->group_by(array('field_group_1', ... ,'field_group_n'));
$result = $this->db->get('mytable');
so $result will have what you need!
Related
Good day all, hope you can help!
I have been toiling with this Query for a while now, and I am sure it will be relatively simple to fix!
I use the query to return all of the values from one table, along with a count of votes from one table, and a count of comments from another.
I have got it to work for loading an individual record
DCount('[query_id]','[comments]','[query_id]=" & Target & "')
However if I add something similar to the query that returns every query_id, the count shows the same for them all.
Is there a different function I can use than DCount to achieve this?
My previous issue was using count, and as the query had non unique data it was counting all votes from a person (i.e if I had made 6 votes, the count would show as 6 for any record my user id was attached to)
Happy to provide any further detail regarding the query.
You may be after something like:
DCount("*","[comments]","[person_id] = " & [Target] & "")
where [Target] is the field holding the PersonId of the other table.
I perhaps didn't ask the question in the best possible way, but I have managed to get the results I expected by using sub select statements in the SELECT clause
Just in case someone else doesn't know how to word or ask a question, Andre posted a very helpful comment to my original question above, advising the following link.
How to ask a good SQL question
SELECT issues.query_id, issues.query_raised_by, issues.query_raised_date, issues.query_summary, issues.query_status, issues.query_status_date, issues.query_detail, issues.query_response
(SELECT COUNT(*) FROM vote WHERE query_id = issues.query_id) AS voteCount,
(SELECT COUNT(*) FROM comments WHERE query_id = issues.query_id) AS commentCount
I have a User model that has many Post.
I want to get, on a single query, a list of users IDs, ordered by name, and include the ID of their last post.
Is there a way to do this using the ActiveRecord API instead of a SQL query like the following?
SELECT users.id,
(SELECT id FROM posts
WHERE user_id = users.id
ORDER BY id DESC LIMIT 1) AS last_post_id
FROM users
ORDER BY id ASC;
You should be able to do this with the query generator:
User.joins(:posts).group('users.id').order('users.id').pluck(:id, 'MAX(posts.id)')
There's a lot of options on the relationship you can use to get data out of it. pluck is handy for getting values independent of models.
Update: To get models instead:
User.joins(:posts).group('users.id').order('users.id').select('users.*', 'MAX(posts.id) AS max_post_id')
That will create a field called max_post_id which works as any other attribute.
I am using NHibernate and I my requirement is that I have 2 tables, User and Ticket. I want all the records that are in User but not in Ticket. The Ticket table has UserId as reference key to the Primary key ID of User table. Below is my code,
RegNotTickTemplate.Criteria = DetachedCriteria.For(typeof(User));
RegNotTickTemplate.Criteria.Add(Subqueries.PropertyNotIn("ID",DetachedCriteria.For(typeof(Ticket))
.SetProjection(Projections.Property("UserID"))));
The above query doesnt return correct set of records.
As an alternative, you could try using HQL. I never use Criteria as I find HQL more readable (it is almost the same as SQL except you get to query based on the entities rather than the tables).
Chapter 13. HQL: The Hibernate Query Language
IQuery query = Session.CreateQuery(
"from User where Id not in (select UserId from Ticket)");
query.List<User>();
If that is still no good, you can always do an SQL query
ISQLQuery query = Session.CreateSQLQuery(sql);
What you are missing is: the count of tickets for this user should be greater than zero. Here is how you can implement it:
RegNotTickTemplate.Criteria = DetachedCriteria.For(typeof(User));
RegNotTickTemplate.Criteria.Add(Subqueries.PropertyIn("Id",
DetachedCriteria.For<Ticket>()
.SetProjection(Projections.GroupProperty("User"))
.Add(Restrictions.Eq(Projections.RowCount(), 0))));
If you don't want the count of rows you can do the following:
RegNotTickTemplate.Criteria = DetachedCriteria.For(typeof(User),"user");
RegNotTickTemplate.Criteria.Add(Subqueries.Exists(DetachedCriteria.For<Ticket>("ticket")
.SetProjection(Projections.Property("User"))
.Add(Restrictions.EqProperty("user.Id", "User"))));
"SELECT * from posts A, categories B where A.active='1'
AND A.category=B.CATID order by A.time_added desc
limit $pagingstart, $config[items_per_page]";
I think it says selects the rows from the 'posts' table such that the active entry in each row is equal to 1 but I don't understand the rest. Please explain. Thank you.
It selects the columns from Posts (referred to with the alias "A"), and the associated for from Categories (referred to as "B") for each post, where:
Posts.Active = 1
The post's category exist in the "Categories" table (if a post doesn't have a matching category in this table, the row won't be returned)
Orders the results by A.Time_added (in decending order, newest to oldest)
Returns just "$config[items_per_page]" rows, starting with "$pagingstart"
I'm not sure what brand of SQL this is, as I don't recognize the limit statement or the $variables, but that's the gist.
You'll get rows
from A and B that where category and CATID match ("intersection" bit of a Venn Diagram)
The rows for A are filtered to those where Active = 1
sorted by time_added. latest first
limit says y rows startig at row x. x and y are determined by the sort
posts A, categories B is a such called "implicit JOIN". It returns all possible combinations of records from A and B which are later filtered by the WHERE conditions.
Explicit join syntax is much more readable:
SELECT *
FROM posts A
JOIN categories B
ON B.CATID = A.category
WHERE A.active='1'
ORDER BY
A.time_added DESC
LIMIT $pagingstart, $config[items_per_page]
This means: "for each record from A, take all records from B whose catid is the same as A's category".
ORDER BY A.time_added DESC makes your posts to return from latest to earliest.
LIMIT 100, 10 makes the query to return only posts from 100th to 110th.
It looks like this is trying to select all active posts, order them with the newest at the top, and limit the number of records to fit on a page. The semantics of A.active='1' probably mean that the post is active, but I'm guessing.
It looks like MySQL with PHP.
This selects entries from posts and categories, joining them together where posts.category=categories.CATID. It filters out all rows where posts.active!=1, and then orders by descending posts.time_added, returning at most $config[items_per_page] items starting from $pagingstart.
It selects all the active posts (and their category), newest first. However, it has a paging mechanism, so it shows only $config[items_per_page] posts starting at number $pagingstart.
Select the rows from the posts table and the categories table, joined into a single table by the category ID (using what I call a lazy join, but that may just be my opinion and I'm not really a database guy), sorted in descending order by the time added, displaying only $items_per_page records starting at $pagingstart.
It select all columns from table posts and categories where posts.active is equal 1 and where posts.category is joined to the categories.catid and this is ordered by posts.time_added a limit start and end is set by the two variables $pagingstart, $config[items_per_page]
It's saying:
1) Select everything from both Posts & Categories where Posts.Active = 1 and Posts.Category = Category.CATID.
2) The Order by statement then specifies that they should be presented (from top to bottom) with the newest Post.Time_Added first.
3) Finally, the limit clause says (I think, I don't use limit very often): Only grab $spagingstart (a variable which has been set at some point) number of items, and only display $config[items_per_page] at a time.
I have the following table structure and I want a turn the query into a NH criteria but I'm not sure how to incorporate the correct 'Projection', does anyone know how?
And the query I want to turn into a Criteria:
select ComponentId from Table_1
where [Name] = 'Contact' or [Name] = 'CurrencyPair'
group by ComponentId
having count(VersionId) = 2
I came across this question when trying to find a solution to my problem.
This post was useful.
In my case I was trying to return all records which have all the sub records the user specifies.
I ended up using a sub query which filters the sub records to the ones the user specified and returns the count, and checking that the count of the sub query equals the number of sub records the user specified.
Bit different from your scenario, but hope helps.