Converting methods in model to scope : Rails3 - ruby-on-rails-3

I have two methods defined in my model Project working correctly.
1. def completed(user)
Project.find_by_sql(["Select p.id from bids b LEFT JOIN tasks t ON b.task_id=t.id LEFT JOIN projects p ON p.id = t.project_id where(b.bidder_id=? and b.status=? and p.status=?) group by p.id", user.id, 'ACCEPTED', 'COMPLETE']).count
end
2. def current(user)
Project.find_by_sql(["Select p.id from bids b LEFT JOIN tasks t ON b.task_id=t.id LEFT JOIN projects p ON p.id = t.project_id where(b.bidder_id=? and b.status=? and p.status in ('LAUNCHED', 'CONFIRM', 'STAFFED', 'OVERDUE')) group by p.id", user.id, 'ACCEPTED']).count
end
When I am converting these two into scope in Project model as
1. `scope :completed, proc{|user| joins("LEFT JOIN tasks t ON t.project_id=projects.id LEFT JOIN bids b ON b.task_id=t.id where(b.bidder_id='#{user.id}' and b.status='ACCEPTED' and p.status='#{COMPLETE_STATUS}')").count("DISTINCT p.id")}`
2. `scope :current, proc{|user| joins("LEFT JOIN tasks t ON t.project_id=projects.id LEFT JOIN bids b ON b.task_id=t.id where(b.bidder_id='#{user.id}' and b.status='ACCEPTED' and p.status IN ('#{LAUNCHED_STATUS}', '#{CONFIRM_STATUS}', '#{STAFFED_STATUS}', '#{OVERDUE_STATUS}')) group by p.id").count("DISTINCT p.id")}`
I am getting error as : ActionView::Template::Error (PG::Error: ERROR: missing FROM-clause entry for table "p"
Please suggest me, how to write these two scope statements correctly. Thanks.

I don't think a scope is the better solution to result a count because a scope is used in order to have a filtered list of objects.
Anyway, your error seems to come from you try to call a table called "p". "p" doesn't exist because this is an alias in your method that you haven't declare in your scope.
To solve this you just need to replace "p" to "projects".
scope :completed, proc{|user| joins("LEFT JOIN tasks t ON t.project_id=projects.id LEFT JOIN bids b ON b.task_id=t.id where(b.bidder_id='#{user.id}' and b.status='ACCEPTED' and projects.status='#{COMPLETE_STATUS}')").count("DISTINCT projects.id")}
scope :current, proc{|user| joins("LEFT JOIN tasks t ON t.project_id=projects.id LEFT JOIN bids b ON b.task_id=t.id where(b.bidder_id='#{user.id}' and b.status='ACCEPTED' and projects.status IN ('#{LAUNCHED_STATUS}', '#{CONFIRM_STATUS}', '#{STAFFED_STATUS}', '#{OVERDUE_STATUS}')) group by projects.id").count("DISTINCT projects.id")}
I hope this help

Related

Problem with the joining of SQL tables via relationships

I am currently having problems trying the run a query for some tables.
Below is what I am trying to do, I just can't seem to get it to work.
I have also duplicated constituent and gifts to show you the relations between soft credit and gifts/constituents
Link to Table Relations Image
SELECT
Constituent.lookup_id,
Constituent.name,
SplitGifts.amount,
SplitGifts.giftaidamount
FROM
dbo.Gifts Gifts
INNER JOIN dbo.Constituent Constituent
ON Constituent.id = Gifts.constituent_id
INNER JOIN dbo.SplitGifts SplitGifts
ON SplitGifts.giftid = Gifts.id
LEFT JOIN dbo.SoftCredit SoftCredit
ON SoftCredit.giftid = Gifts.id
INNER JOIN dbo.Constituent Constituent_1
ON Constituent_1.id = SoftCredit.constituentid
INNER JOIN dbo.Gifts Gifts_1
ON Gifts_1.id = SoftCredit.giftid
INNER JOIN dbo.Package Package
ON Package.id = SplitGifts.packageid
WHERE
Package.lookup_id = N'CORPCHAL'
Basically, I want the
amount and gift_aid_amount from [SplitGifts]
Constituent Name & lookup_id from [constituent] to show up for all Gifts however if a soft credit exists for that gift I need it to get the same fields via the [SoftCredit] table -> Gifts -> SplitGifts -> Fields
You could try if the query below works.
SELECT
Constituent.lookup_id,
Constituent.name,
SplitGifts.amount,
SplitGifts.giftaidamount
FROM
dbo.Gifts Gifts
LEFT JOIN dbo.SoftCredit SoftCredit ON SoftCredit.giftid = Gifts.id
INNER JOIN dbo.Gifts Gifts_1 ON
Gifts_1.id = SoftCredit.giftid OR
(SoftCredit.giftid IS NULL AND Gifts_1.id = Gifts.id)
INNER JOIN dbo.Constituent Constituent ON
Constituent.id = SoftCredit.constituentid OR
(SoftCredit.constituentid IS NULL AND Constituent.id = Gifts_1.constituent_id)
INNER JOIN dbo.SplitGifts SplitGifts ON SplitGifts.giftid = Gifts_1.id
INNER JOIN dbo.Package Package ON Package.id = SplitGifts.packageid
WHERE
Package.lookup_id = N'CORPCHAL'
It joins back to table Gifts (using alias Gifts_1) on the gift reference in SoftCredit or to itself if there is no SoftCredit.
Table Constituent is joined in a similar fashion: it joins on the value of SoftCredit.constituentid and when NULL, it falls back to Gifts_1.constituent_id.
All next joins regarding the gift should refer to Gifts_1 then.
I have not tested it though. But it might give you a hint in a possible solution direction.

Access 'Join not supported' Moving LEFT Join

I've done some research here and I understand that in Access nested joins cause issues.
I believe that is the issue in the first example.
SELECT
Recipe_Classes.RecipeClassDescription,
Recipes.RecipeTitle,
Recipes.Preparation,
Ingredients.IngredientName,
Recipe_Ingredients.RecipeSeqNo,
Recipe_Ingredients.Amount,
Measurements.MeasurementDescription
FROM (((
Recipe_Classes
LEFT JOIN Recipes
ON Recipe_Classes.RecipeClassID = Recipes.RecipeClassID)
INNER JOIN Recipe_Ingredients
ON Recipes.RecipeID = Recipe_Ingredients.RecipeID)
INNER JOIN Ingredients
ON Ingredients.IngredientID = Recipe_Ingredients.IngredientID)
INNER JOIN Measurements
ON Measurements.MeasureAmountID = Recipe_Ingredients.MeasureAmountID
ORDER BY RecipeTitle, RecipeSeqNo;
I made an attempt to remove the nesting and created a right join in this example
SELECT
Recipe_Classes.RecipeClassDescription,
Recipes.RecipeTitle,
Recipes.Preparation,
Ingredients.IngredientName,
Recipe_Ingredients.RecipeSeqNo,
Recipe_Ingredients.Amount,
Measurements.MeasurementDescription
FROM (((
Ingredients
INNER JOIN Recipe_Ingredients
ON Ingredeints.IngredientID = Recipe_Ingredients.IngredientID)
INNER JOIN Measurements
ON Measurements.MeasureAmountID = Recipe_Ingredients.MeasureAmountID)
INNER JOIN Recipes
ON Recipes.RecipeID = Recipe_Ingredients.RecipeID)
RIGHT JOIN Recipe_Classes
ON Recipe_Classes.RecipeClassID = Recipes.RecipeClassID
ORDER BY RecipeTitle, RecipeSeqNo;
Can anyone point me in the right direction?
The issue may be the left join that is not needed. Try this from clause:
SELECT Recipe_Classes.RecipeClassDescription,
Recipes.RecipeTitle,
Recipes.Preparation,
Ingredients.IngredientName,
Recipe_Ingredients.RecipeSeqNo,
Recipe_Ingredients.Amount,
Measurements.MeasurementDescription
FROM (((Recipes LEFT JOIN
Recipe_Classes
ON Recipe_Classes.RecipeClassID = Recipes.RecipeClassID
) LEFT JOIN
Recipe_Ingredients
ON Recipes.RecipeID = Recipe_Ingredients.RecipeID
) LEFT JOIN
Ingredients
ON Ingredients.IngredientID = Recipe_Ingredients.IngredientID
) LEFT JOIN Measurements
ON Measurements.MeasureAmountID = Recipe_Ingredients.MeasureAmountID
ORDER BY RecipeTitle, RecipeSeqNo;
Once you start with LEFT JOINs, generally all the remaining joins should also be LEFT JOINs.
Since your main focal point table is Recipe_Ingredients, consider starting with this table in FROM and then JOIN the other parent tables and even nest the Recipes and Recipe_Classes pair:
SELECT
c.RecipeClassDescription,
r.RecipeTitle,
r.Preparation,
i.IngredientName,
ri.RecipeSeqNo,
ri.Amount,
m.MeasurementDescription
FROM
((Recipe_Ingredients ri
INNER JOIN (Recipes r
RIGHT JOIN Recipe_Classes c
ON c.RecipeClassID = r.RecipeClassID)
ON r.RecipeID = ri.RecipeID)
INNER JOIN Ingredients i
ON i.IngredientID = ri.IngredientID)
INNER JOIN Measurements m
ON m.MeasureAmountID = ri.MeasureAmountID
ORDER BY r.RecipeTitle, ri.RecipeSeqNo;
Of course this is untested without data. Due to Access' JOIN requirements like parnetheses, it is often recommended for new users to build complex queries with MS Access' GUI Query Design then modify generated SQL as needed.

Getting data from a join tables tu sub categories in access with SQL

I created this relationship with Access database but when I am creating a query to return the values I dont get the all the data.
How can I get all the data from tube and tmc tables by ProjectType or ProjectId ?
So I should get something like this query but the query generated by access is not working
SELECT Project.ProjectName,
ProjectSubTypesId.ProjectSubTypesId,
Tube.TubeName, Tube.Duration,
Tmc.TmcName
FROM Tmc
INNER JOIN
(Tube INNER JOIN
(Project INNER JOIN ProjectSubTypesId ON Project.ProjectId = ProjectSubTypesId.ProjectId)
ON Tube.TubeId = ProjectSubTypesId.TubeId) ON Tmc.TmcId = ProjectSubTypesId.TmcId;
Try this:
SELECT Project.ProjectName,
ProjectSubTypesId.ProjectSubTypesId
FROM (
(ProjectSubTypes
INNER JOIN Project USING (ProjectId)
)
INNER JOIN Tube USING(TubeId)
)
INNER JOIN Tmc USING(TmcId)
GROUP BY ProjectSubTypes.ProjectId, ProjectSubTypes.TubeId, ProjectSubTypes.TmcId
ORDER BY ProjectSubTypes.ProjectId;
Something like this work?
SELECT Project.ProjectName,
ProjectSubTypesId.ProjectSubTypesId,
Tube.TubeName, Tube.Duration,
Tmc.TmcName
FROM ((ProjectSubTypes
INNER JOIN Project ON Project.ProjectId = ProjectSubTypes.ProjectId)
INNER JOIN Tube ON Tube.TubeId = ProjectSubTypes.TubeId)
INNER JOIN Tmc ON Tmc.TmcId = ProjectSubTypes.TmcId
ORDER BY ProjectSubTypes.ProjectId;
This should give you a list of all sub-types along with their corresponding Tube, Tmc, and Project data.
If it is possible to have multiple ProjectSubTypes rows with the same TubeId and TmcId then consider adding this line before the ORDER BY line:
GROUP BY ProjectSubTypes.ProjectId, ProjectSubTypes.TubeId, ProjectSubTypes.TmcId

Ambiguous outer join in MS Access

Trying to create an outer join on two other joined tables when recieving this error - I just dont see how to create two separate queries to make it work. Subqueries don't seem to work either, any help appreciated. I get errors for the below query, thanks.
SELECT
CardHeader.CardID, CardHeader.CardDescription, CardHeader.GloveSize,
CardHeader.GloveDescription, CardDetail.Bin, CardDetail.ItemID, Items.ItemDescription,
Items.VCatalogID, CardDetail.ChargeCode, CardDetail.Quantity, Items.Cost, CardColors.ColorID
FROM
((Items
INNER JOIN
(CardHeader INNER JOIN CardDetail ON CardHeader.CardID = CardDetail.CardID) ON Items.ItemID = CardDetail.ItemID)
LEFT JOIN
CardColors ON CardDetail.ItemID = CardColors.ItemID)
INNER JOIN
Colors ON CardColors.ColorID = Colors.ID
ORDER BY
CardHeader.CardID;
I tried the following which runs but asks for the following parameters (which it shouldnt)
CardHeader.ID, MainQry.CardID
SELECT
MainQry.ID, MainQry.CardDescription, MainQry.GloveSize,
MainQry.GloveDescription, MainQry.Bin, MainQry.ItemID,
MainQry.ItemDescription, MainQry.VCatalogID, MainQry.ChargeCode,
MainQry.Quantity, MainQry.Cost, SubQry.ColorID
FROM
(SELECT
CardHeader.ID, CardHeader.CardDescription, CardHeader.GloveSize,
CardHeader.GloveDescription, CardDetail.Bin,
CardDetail.ItemID, Items.ItemDescription, Items.VCatalogID,
CardDetail.ChargeCode, CardDetail.Quantity, Items.Cost
FROM
Items
INNER JOIN
(CardHeader
INNER JOIN
CardDetail ON CardHeader.CardID = CardDetail.CardID) ON Items.ItemID = CardDetail.ItemID
) AS MainQry
LEFT JOIN
(SELECT
CardColors.ItemID, CardColors.ColorID
FROM
CardColors
INNER JOIN
Colors ON CardColors.ColorID = Colors.ID) AS SubQry ON MainQry.ItemID = SubQry.ItemID
ORDER BY
MainQry.CardID;
The second SQL statement can be corrected by reference to the first statement and the error. The error is that both CardHeader.ID and MainQry.CardID are prompting for a parameter, which indicates that the inner statement should include CardHeader.CardID, rather than CardHeader.ID

ActiveRecord joins syntax

I need to express the following join condition using ActiveRecord:
SELECT ...
FROM U
LEFT OUTER JOIN F ON U.key = F.foreign_key
AND F.key = ?
WHERE ...
where ? is substituted at run time.
The following causes a SQL-syntax error:
joins("LEFT OUTER JOIN F on U.key = F.foreign_key AND F.key=?", key)
I can't seem to determine if ActiveRecord supports this 'dynamic substitution' (whatever this is called).
Adding the restriction (where("F.key=?", key)) in the WHERE clause will collapse the OUTER JOIN to a JOIN.
This syntax worked:
joins("LEFT OUTER JOIN F on U.key = F.foreign_key AND F.key=#{key}")