CakePHP SQL-query count - sql

I have a problem concerning CakePHP SQL-queries. I need to fetch products from the database where shop_id is given and then count the products. All I need is Product.url and its count.
This will do the trick in plain SQL:
SELECT url,COUNT(*) as count FROM products GROUP BY url ORDER BY count DESC;
This one I used to get all products relating to shops:
$this->Product->find('all', array('conditions' => array('Product.shop_id'=>$id)));
That works correctly, but I need to convert that SQL-query above to CakePHP.
I tried something like this:
$this->Product->find('count', array('conditions' => array('Product.shop_id'=>$id),
'fields'=>array('Product.url','Product.id'),
'order'=>'count DESC',
'group'=>'Product.url'));
That returns only an int. But if I run that SLQ-query presented above in mysql server, I get two columns: url and count. How do I get the same results with CakePHP?

You can try this:
$data = $this->Post->query(
"SELECT COUNT(id),MONTH(created) FROM posts GROUP BY YEAR(created), MONTH(created);"
);

The most easiest way to do this:
$this->Product->query("SELECT url,COUNT(*) as count FROM products GROUP BY url ORDER BY count DESC;");
...at least for me.

Try the following code:
$this->Product->virtualFields['CNT_PRODUCTS'] = 0;
$this->Product->find('count', array('conditions' => array('Product.shop_id' => $id),
'fields' => array('Product.id', 'Product.url', 'count(*) as CNT_PRODUCTS'),
'order' => array('CNT_PRODUCTS' => 'DESC'),
'group' => 'Product.url'));

Related

Phalcon Model order by item popularity (number of appearances)

I'm sure I have done something like this before, but can't find it and google not being helpful.
Using Phalcon model if possible, I want to select the items from a table whose ID appears the most - i.e. 10 most popular items ordered by popularity. Is this possible using Model::find("conditions")? I do I have to use PHQL for this?
using model::find
Model::find([
'columns' => 'id,count(id) as counter',
'group' => 'id',
'order' => 'counter DESC'
]);
PHQL:
$this->modelsManager->executeQuery('SELECT count(id) AS counter,id FROM ModelName GROUP BY id ORDER BY counter DESC');
find() does have a group clause, but I don't think it's possible to do what you want because you also need to do a count.
Talal's answer is close, but won't work if you want a list of model objects.
Something like this should work:
$Results = $this->modelsManager->executeQuery('SELECT * FROM ModelName GROUP BY id ORDER BY count(id) DESC LIMIT 10');
$Results->setHydrationMode(\Phalcon\Mvc\Model\Resultset::HYDRATE_RECORDS);
Setting the hydration mode may not be necessary, as Phalcon may default to that mode based on the fact the query is asking for *.

Convert SQL to Linq - Where, Groupby and Having

The proper syntax in Linq for this SQL query is eluding me. I'd appreciate any hand with this.
SQL:
SELECT TOP 1 posdate
FROM dailypos
GROUP BY posdate
HAVING Count(DISTINCT customernumber) = 3
ORDER BY posdate DESC)
Essentially, I get files from 3 different customers and I need a quick way to determine the most recent date for which I have data from all 3. I'm open to a different approach, but this SQL works for what I need.
I can do the group, but I don't know how to handle the 4th line (HAVING Count(Distinct...))
Thanks in advance.
Try something like this:
var result = context.dailypos
.GroupBy(x => x.posdate)
.Where(g => g.Select(x => x.customernumber).Distinct().Count() == 3)
.Select(g => g.Key)
.OrderByDescending(x => x)
.Take(1);

CakePHP nesting select query

I have 3 db tables: books(id, title, author,...) and orders(id, book_id, user_id,...) and users(id, name, username,...) and I would like to get the titles of the books ordered by given user.
I prepared query using query() method:
$this->set('user_orders', $this->Order->query("SELECT orders.id, orders.status,
(SELECT books.title FROM books WHERE books.id = orders.book_id) as `titles`
FROM orders WHERE orders.user_id = ".$this->Auth->user('id').""));
Now, I would like to obtain the same result but using find() method:
$this->set('user_orders', $this->Order->find('all', array(
'fields' => array(
'Order.id',
'status',
'Order.book_id',
'Book.title' => $this->Book->find('first',array(
'fields' => 'Book.title',
'conditions'=> array('Book.id = Order.id')
)),
),
'conditions' => array('user_id' => $this->Auth->user('id')))));
However, it does not work. How it should be corrected to obtain the same effect like in code above?
Greetings
You might want to read up on the ContainableBehavior for this: http://book.cakephp.org/1.3/en/view/1323/Containable.
And, as Kaklon suggested: please be more specific about what is/isn't working...

RoR table join with "where" needed on both tables

I'm having trouble wrapping my head around joining tables. I have a one_to_many relationship between Locations and Listings. Locations have a longitude and latitude, as well as it's primary key: zipcode. Listings have a title and zipcode.
Listing.where("title LIKE ?", "%#{params[:search2]}%")
Location.where(:lat => #min_lat..#max_lat, :lon => #min_lon..#max_lon)
I'd basically Like to combine these two statements so that I can get all Listings within a given range of a zipcode, which is determnied by using a range of longitudes and latitudes. I can't figure out how to do this in Ruby on Rails in a fashion where I don't have to do separate SQL finds and loop through the data in my code to find the correct data.
Edit Updated code:
#results=Location.joins(:listings).where(:listings => ["title LIKE ?", "%#{params[:search2]}%"], :locations => {:zipcode => params[:searchZip]})
SQL output:SELECT "locations".* FROM "locations" INNER JOIN "listings" ON "listings"."location_id" = "locations"."zipcode" WHERE ("locations"."listings" IN ('title LIKE ?', '%fish%')) AND ("locations"."zipcode" = 44012)
I don't know why it is doing "locations"."listings" (which gives an error), or where the IN is coming from.
I suggest using ARel as opposed to writing your own SQL:
Listing.joins(:location).
where(:listings => {:lat => #min_lat..#max_lat, :lon => #min_lon..#max_lon},
:location => ["title LIKE ?", "%#{params[:search2]}%"])
If I am understanding correctly that Location has_many :listings, then this query will return all of the listings in the location range with matching titles:
Listing.joins(:location).where(
'listings.title LIKE ? AND
locations.lat BETWEEN ? AND ? AND
locations.lon BETWEEN ? AND ?',
"%#{params[:search2]}%", #min_lat, #max_lat, #min_lon, #max_lon)
Location.joins(:listings).where(:listings => {:lat => #min_lat..#max_lat, :lon => #min_lon..#max_lon} )

rails group by multiple columns

i have budgets table with emptype_id and calendar_id actual_head, estimated_head
when i do Budgets.sum(:actual_head ,:group=>"emptype_id,calendar_id") i do not get the result grouped by the above two columns but only by the emptype_id
however when i check the log the sql query is right
SELECT sum(`budgets`.actual_head) AS sum_actual_head, emptype_id,calendar_id AS emptype_id_calendar_id FROM `budgets` GROUP BY emptype_id,calendar_id
has 103 rows
I wanted to iterate through each emptype_id and calendar_id to get a sum of actual_head
and do some calculations on it.
Grouping with multiple columns cannot be supported by rails. You have to use a regular find all:
budgets = Budgets.find(:all,
:select => "emptype_id, calendar_id, sum(budgets.actual_head) AS sum_actual_head",
:group => "emptype_id, calendar_id")
budgets.each { |budget| puts budget.sum_actual_head }
I cheat. Do :group => ["emptype_id,calendar_id"].
Not want you nor I want, but this works at least.
I'm not sure of this, buy try :group => [:emptype_id, :calendar_id]