Symfony and DQL syntax - symfony1

I apologize for the beginner question, but I'm struggling with what seems should be a simple query. I can get it to work perfectly in MySQL, but can't get it to work in my symfony application. Essentially, this is all I'm trying to do:
SELECT *
FROM benefits b
WHERE b.company_id = X
X =
SELECT id
FROM company c
WHERE c.user_id = ($this->getUser()->getGuardUser()->getId())
I've tried many join statements but still can't get it to work with the result I want, such as:
public function executeIndex(sfWebRequest $request)
{
$this->benefitss = Doctrine_Core::getTable('benefits')
->createQuery('b')
->where('user_id = ?', '$this->getUser()->getGuardUser()->getId()')
->leftJoin('b.Company c')
->andWhere('c.user_id = ?', '$this->getUser()->getGuardUser()->getId()')
->execute();
}
Here's my condensed schema:
Benefits
columns
id
user_id
company_id
name
relations
User {class: sfGuardUser}
Company
Company
columns
id
user_id
name
relations
User {class: sfGuardUser}
sfGuardUser
columns
id
also of note: the user is not assigned a company_id b/c not all users will have companies according to my user definitions.
Any help for this wretched beginner would be much appreciated. :)
Update 8/27/11:
This gets the results I want:
$this->benefitss = Doctrine_Core::getTable('benefits')
->createQuery('b')
->leftJoin('b.Company c')
->Where('c.user_id = ?', '1')
->execute();
Where the '1' needs to be the current user's id. But when I change the where clause to:
->Where('c.user_id = ?', '$this->getUser()->getGuardUser()->getId()')
I get no results.
Any ideas?

Don't put $this->getUser()->getGuardUser()->getId() in ''.

I got it figured. Here's how (I'm obviously a beginner):
$this->benefitss = Doctrine_Core::getTable('benefits')
->createQuery('b')
->leftJoin('b.Company c')
->Where('c.user_id = ?', $this->getUser()->getGuardUser()->getId())
->execute();

Related

How to query the result of a method in Ruby (rails)

I'm struggling with a particular feature.
In my users model I have a method to work out their age based on the current date less their first order date.
I'd like to be able to find all users who are older than X days. I can find active users by querying a column called state for 'active' users. But I'm unsure how to query the result of the age method to find users older than X.
Does anyone have any ideas?
Many thanks and seasons greetings.
**Edit
In postgresql I would write;
WITH
firstbill as (
SELECT
DISTINCT(user_id) as customer,
DATE(MIN(billed_at)) as first_order
FROM orders
WHERE state = 'shipped'
GROUP BY 1
ORDER BY 1)
SELECT count*
FROM
(SELECT *, (current_date - first_order) as age
FROM firstbill
JOIN users on users.id = customer) as t2
WHERE age >= 21
I have tried using User.find_by_sql["above query"] but that returns an array not activerecord relation which makes any further joins a little harder
You cannot really query for the return value of a method. Because to do so, you need to load all users and then call that method on every user, like this User.all.select(&:your_method?). That will be very slow if you have many users.
But for your particular example you can write something like this to let the database return the correct users (assuming you have a first_ordercolumn on your user):
User.where('first_order <= ?', 90.days.ago)
or
User.where('first_order <= ?', 1.month.ago)
I think the following startment should return the same users than your Postgresql example:
User.
select('users.*, MIN(DATE(orders.billed_at)) AS first_order_on').
joins('orders ON orders.user_id = users.id'). # just `(:orders)` with `has_many :order` on User
where('orders.state = ?', 'shipped').
group('users.id').
having('first_order_on <= ?', 21.days.ago.to_date)
Solved by using
scope :acquired, User.joins(:orders).where("orders.state = ?", "shipped")
scope :older_than_age, ->(age) {
acquired.group("users.id").having("(current_date - date(min(orders.shipped_at))) >= ?", age)
}

Write nested query in rails activerecord style

How do i write this query in rails active record style
SELECT COUNT(o.id) no_of_orders,
SUM(o.total) total,
SUM(o.shipping) shipping
FROM orders o JOIN
(
SELECT DISTINCT order_id
FROM designer_orders
WHERE state IN('pending', 'dispatched', 'completed')
) d
ON o.id = d.order_id
You can do with an explicit query, you have 2 manner to do that:
Model.where("MYSQL_QUERY")
or
Model.find_by_sql("MYSQL_QUERY")
http://apidock.com/rails/ActiveRecord/Base/find_by_sql/class
OR
In Rails Style with a little more steps (probably can be done with less):
order_ids = DesignerOrder.where("state IN (?)", ['pending', 'dispatched', 'completed']).select(:order_id).distinct
partial_result = Order.where("id IN (?)", order_ids)
no_of_orders = partial_result.count
total_sum = partial_result.sum(:total)
shipping_sum = partial_result.sum(:shipping)
You can also do it like this
Order
.select('
COUNT(o.id) no_of_orders,
SUM(o.total) total,
SUM(o.shipping) shipping
')
.from('orders o')
.joins("
(#{
DesignerOrders
.select("DISTINCT order_id")
.where("state IN('pending', 'dispatched', 'completed')")
}) d on o.id = d.order_id
")
I didn't actually run this but the concept is valid. You don't even need an active record model if you use 'from'. We've used techniques like this to do AR style queries for extremely complex SQL and it's made our lives a lot easier.

rails how to find with no associated records

I know that this will be an easy one but I'm having real issues working it out.
I have users that can have_many results. I'm trying to work out how to return users that don't yet have any results to the #starters object(from the controller).
#users = #event.entires
#starters = #users.where("results = ?", 0)
could anyone explain how i would check if a user has no results?
Best solution (as MrYoshiji commented)
#starters = #users.includes(:results).where(results: { id: nil })
This will execute the same query as the one in my second solution.
Other SQL solution
You could use a LEFT OUTER JOIN. This way, you will always have all the results from the "left" table (users) but you will also have matching records for the "right" table (results) eventhough there are non, which will leave you with empty fields that you can check.
#starters = #users.joins("LEFT OUTER JOIN results ON results.user_id = users.id").where("results.user_id IS NULL")
In your case, replace users with the name of your "user" model.
Other Ruby solution
#starters = #users.select { |u| !!u.results }
Here !! will force conversion to a boolean, if there are no results, u.results will return [] (empty array). And !![] equals true.
Try left joining and finding which one is null
#users.joins("LEFT OUTER JOIN user ON user.id = result.user_id").where("result.id IS NULL")
If your #users is an Array, try:
#starters = #users.select { |u| u.results.empty? }
This should get all of the users that do not have any results:
#starters = ActiveRecord::Base.execute("select * from users where id not in (select user_id from results)")
Another way to do this would be the following:
User.where("id not in ?", "(select user_id from results)")

Multiple Doctrine query to pull a specific record using sfGuard plugin

I am trying to pull a specific set of records from a table called Faculty, by retrieving a specific parameter from another table. I am getting the id from the sfGuard User, then retrieving the record from the ID. From there I would like to pull out the department title from that table and display only records from Faculty with that department title.
This is what I have in my actions.class:
$userId = $this->getUser()->getGuardUser()->getId();
$userRecord = Doctrine_Query::create()
->from ('sfGuardUser s')
->where("s.id = '$userId'")
->limit('1')
->execute();
$userDept = $userRecord['department_title'];
$this->facultyAdminFind = Doctrine_Query::create()
->from ("Faculty a")
->where("a.notables LIKE ?", "%$userDept%")
->execute();
After doing some troubleshooting, I know I am pulling the correct ID and the correct record from sfGuardUser table. I just can't seem to pull the department title from the sfGuardUser record.
The loop is coming up with nothing.
If I change $userDept = $userRecord['department_title']; to $userDept = "Engineering";
Update to questions below:
I am getting the userID, then asking for the department_title of that ID. I can get the id using getGuardUser(), but not 'department_title' right? If so, what would that syntax look like?
I am sure there is a department title and there are no misspellings. I actually worked from this backwrds to verify all variables that were being pulled
First I did this:
$this->facultyAdminFind = Doctrine_Query::create()
->from ('sfGuardUser s')
->where("s.id = '$userId'")
->limit('1')
->execute();
which returned the correct record in the loop and I was able to use $item['department_title"] in the template to call the department title correctly. So I know I am getting the correct userID and calling the correct record into $userRecord.
Also, inside Faculty::notables there are strings with Engineering. That is why I did this:
$userDept = "Engineering";
And I was able to get a result of all records with Engineering in notables.
This is what I found that works:
Per ProdigitalSon I was able to look at the model and figure out how to pull the dept title from the user table. This is working.
$userId = $this->getUser()->getGuardUser()->getDepartmentTitle();
$this->facultyAdminFind = Doctrine_Query::create()
->from ("Faculty a")
->where("a.notables LIKE ?", "%$userId%")
->execute();
UPDATE:
I learned you should not modify the sfGuard schema because if you update the plugin, you would lose the specialized schema. I have added a new class in the main schema, and have a working association between sf_guard_user and department_title.
The issue is I am back to square one with trying to get the department_title from the array.
Here is the added schema:
MyUserProfile:
columns:
id: { type: integer, primary: true, autoincrement: true }
sf_guard_user_id: { type:integer }
department_title: { type: string(255) }
# ... other column definitions
relations:
User:
class: sfGuardUser
foreignType: one
foreignAlias: Profile
local: sf_guard_user_id
onDelete: CASCADE
And this is the query that should work (in my head).
//pulls department limited records for faculty admin
$userId = $this->getUser()->getGuardUser()->getId();
$usergetDept = Doctrine_Query::create()
->from('MyUserProfile d')
->where("d.sf_guard_user_id = '$userId'")
->execute();
$userDept = $usergetDept['department_title'];
$this->facultyAdminFind = Doctrine_Query::create()
->from ("Faculty a")
->where("a.notables LIKE ?", "%$userDept%")
->execute();
This is pulling every record, not just the ones with the department_title. Could I do this easier with a multiple join maybe?
Firs thing that stands out is why are you querying for the user when you already have the user. You dont need to query sfGuardUser again you already have that record from calling myUser::getGuardUser().
So the next thing is are you sure the record youre working with has a department_title property set? Are you sure you didnt mispell the column name either in the schema or in the snippet code? And are us sure that the value in the sfGuardUser::department_title youre working with does in fact match some records in Faculty::notables?
This is how I solved the issue of getting the department_title from the MyUserProfile class
After adding the relation to the schema, you can call the record like this:
$getProfile = $this->getUser()->getProfile();
$userDept = $getProfile['department_title'];
$this->facultyAdminFind = Doctrine_Query::create()
->from ("Faculty a")
->where("a.notables LIKE ?", "%$userDept%")
->execute();

HQL issue with hasMany String

That's the context of this issue:
I have a Grails class:
class User{
long id
static hasMany = [skills: String]
...
}
I'd like to get users from the db on 2 conditions:
set of ids
set of skills (strings)
I wrote this query that works for the ids, but I can't get the skill part working:
User.findAll( "from User
where id in (5067120,5067121,...5067139)" )
For the moment I'm selecting the Users with the right skills manually after this query, but obviously it's not an efficient solution.
How can I solve this?
Thanks!
This should work:
def ids = [5067120L, 5067121L, ...5067139L]
def skills = ['skill 1', 'skill 2']
def users = User.executeQuery(
'select distinct u ' +
'from User u inner join u.skills skills ' +
'where u.id in (:ids) and skills in (:skills)',
[ids: ids, skills: skills])
Note that you don't need to specify the id field if it's a regular long, Grails does that for you.

Resources