Right now I am wasting a query and also losing the order of Users. Was
wondering what t he proper way to do this query is?
@top_tipper_ids = Tip.find_by_sql(“SELECT SUM(tips.amount_cents)
total_tip, tips.client_id FROM tips WHERE tips.vendor_id = #{@user.id}
GROUP BY tips.client_id ORDER BY total_tip”).collect {|e| e.client_id}
I would propose a custom view that exploits SQL powers. I do not know
how
much info you would like to syphon from the user model. Here is what I
think
you can do:
*Code (In User model):
sql_query = “SELECT total_tippers.total_tips AS total_tips,
total_tippers.client_id AS client_id
users.first_name AS first_name,
users.last_name AS surname,
users.add_all_other_fields_you_require AS each_required_field
FROM (
SELECT SUM(tips.amount_cents)AS total_tips, tips.client_id AS
client_id
FROM tips
WHERE tips.vendor_id = #{@user.id}
GROUP BY tips.client_id
ORDER BY total_tip ) AS top_tippers, users
WHERE top_tippers.client_id = users.id”
@top_tippers = self.find_by_sql(sql_query)
Expected/Sample Output (tabulated for the sake of crarity):
I chose to use User model. This is to reflect that the top_tipper
is
a user not the tip itself. (for sense and readability’s sake). In
addition, I think it’s a user who has (many) tips and not the
other way round ([?]).
If you only want to use the user (without making use of the other
data
e.g. total_tips, client_id), as depicted by the “.collect”
operation on
your Tip model, then you can just scrap off the fields in the outer
query so
that it appears like this: sql_query = “SELECT * FROM (
SELECT SUM(tips.amount_cents)AS total_tips, tips.client_id AS
client_id
FROM tips
WHERE tips.vendor_id = #{@user.id}
GROUP BY tips.client_id
ORDER BY total_tip ) AS top_tippers, users
WHERE top_tippers.client_id = users.id” . But be ready to hassle a
bit
in order to find the fields you want. May be you can use
script/console to
figure out, though most geeks discourage testing codes from
script/console.
Caution: I haven’t tested the code; *expect a bug if you use as
it is
*. You may need to customize it to fit your models and tables
details.
(nice one, isn’t it? [?][?])
“A more radical argument for [statistical Natural Language Processing]
is
that human cognition is probabilistic and that language must therefore
be
probabilistic too since it is an integral part of cognition.” – Chris
Manning (1999), Foundations of Statistical Natural Language
Processing.
Right now I am wasting a query and also losing the order of Users. Was
wondering what t he proper way to do this query is?
@top_tipper_ids = Tip.find_by_sql(“SELECT SUM(tips.amount_cents)
total_tip, tips.client_id FROM tips WHERE tips.vendor_id = #{@user.id}
GROUP BY tips.client_id ORDER BY total_tip”).collect {|e| e.client_id}
Thanks for leading me on the right path. Fixed a few errors and it
worked great:
def top_tippers
sql_query = “SELECT top_tippers.total_tips AS total_tips,
top_tippers.client_id AS client_id,
users.login_slug AS login_slug,
users.login AS login
FROM (
SELECT SUM(tips.amount_cents) AS total_tips,
tips.client_id AS client_id
FROM tips
WHERE tips.vendor_id = #{self.id}
GROUP BY tips.client_id
ORDER BY total_tips DESC) AS top_tippers, users
WHERE top_tippers.client_id = users.id” @top_tippers = User.find_by_sql(sql_query)
end
What’s the danger of interpolating the id directly? It is not passed
in any way from the user. It is the primary_key integer ID of the
user. How do I use placeholders when constructing the query?
Whom are you addressing? Please quote when replying in future.
Fixed a few errors and it
worked great:
def top_tippers
sql_query = “SELECT top_tippers.total_tips AS total_tips,
top_tippers.client_id AS client_id,
users.login_slug AS login_slug,
users.login AS login
FROM (
SELECT SUM(tips.amount_cents) AS total_tips,
tips.client_id AS client_id
FROM tips
WHERE tips.vendor_id = #{self.id}
GROUP BY tips.client_id
ORDER BY total_tips DESC) AS top_tippers, users
WHERE top_tippers.client_id = users.id” @top_tippers = User.find_by_sql(sql_query)
end
You probably don’t need to write that much SQL. Again, see if the
Calculations module will help.
What’s the danger of interpolating the id directly? It is not passed
in any way from the user. It is the primary_key integer ID of the
user.
How sure can you be that you won’t get passed a bogus ID?
How do I use placeholders when constructing the query?
Sprite,
I propose a small change. Add a space between the sql_query string and
the @top_tippers variable (for readability sake):
def top_tippers
sql_query = “SELECT top_tippers.total_tips AS total_tips,
top_tippers.client_id AS client_id,
users.login_slug AS login_slug,
users.login AS login
FROM (
SELECT SUM(tips.amount_cents) AS total_tips,
tips.client_id AS client_id
FROM tips
WHERE tips.vendor_id = #{self.id}
GROUP BY tips.client_id
ORDER BY total_tips DESC) AS top_tippers, users
WHERE top_tippers.client_id = users.id”