Hoping an ActiveRecord wizard can help me determine if this kind of query can be done with a AR statement, i.e. without executing the raw SQL or diving into Arel?
I'm getting close but can't seem to figure out how to add the subquery in. I'm on Rails 5.1.1.
SELECT s.id as stock_id, s.count, adjustments.count as
adjustment_count, adjustments.reason as adjustment_reason
FROM
(SELECT * FROM stocks WHERE inventory_id = 6) AS s
LEFT JOIN adjustments
ON (s.id = adjustments.stock_id AND adjustments.reason='run_use')
The end result should be all Stock that have inventory id 6 with the extra columns showing what Adjustment was made to them, if they exist.
If I run the RAW SQL in Navicat I get this result, which is what I'm trying to get via ActiveRecord:
This gets me close, but it just produces stock_ids 11 and 10:
Stock.where(inventory:6)
.left_joins(:adjustments)
.where("adjustments.reason = 'run_use'")
One of these should work for you:
Stock.eager_load(:adjustments)
.where("adjustments.reason = ? OR stocks.inventory_id = ?", "run_use", 6)
or
Stock.eager_load(:adjustments)
.where(adjustments: { reason: "run_use" }, inventory_id = 6)
Hm. It seems you're trying to say:
Give me all Stock that belong to Inventory with id = 6 that also have Adjustments with a reason of 'run use'.
How about something like:
Stock.
where(inventory_id: 6).
joins(:adjustments).
where(adjustments: { reason: 'run_use' })
from the Guides
Related
New to SQL and I am trying to run a query that pulls all our item codes, lot number, and qty on hand.
Each lot number has multiple entries due to adjustments. I need a way of running my query and having it add or subtract to get the actual qty on hand for each lot and only show me lots that are in the negatives. I have tried playing with SSRS but I cant get it right. I'm using SQL 2008R2.
SELECT
IMLAYER.ITEM_CODE
,IMMSTR.ITEM_DESC
,IMLAYER.LOT_NO
,IMLAYER.QTY_ON_HAND
FROM
IMLAYER
INNER JOIN
IMMSTR
ON
IMLAYER.ITEM_CODE = IMMSTR.ITEM_CODE
WHERE
(IMLAYER.QTY_ON_HAND < 0);
I believe I understand the requirements correctly, but if not please comment and I can update the query:
SELECT
M.ITEM_CODE
,M.ITEM_DESC
,L.LOT_NO
,'SUM_OF_QTY_ON_HAND' = SUM(L.QTY_ON_HAND)
FROM
IMLAYER L
INNER JOIN
IMMSTR M
ON L.ITEM_CODE = M.ITEM_CODE
GROUP BY
M.ITEM_CODE
,M.ITEM_DESC
,L.LOT_NO
HAVING
SUM(L.QTY_ON_HAND) < 0
HAVING is the trick you are looking for to be able to use an aggregate function for filtering.
i'm stuck at another point in my little Access 2016 Database. My code looks like the following and i know it probably isn't the cleanest solution but i'm kinda new to this and i tried to educate myself and get some help here already.
I'm trying to play around with the reports now a little bit and i am using this test query which returns all entries of two tables joined together.
As far as i could find out I have this one subquery included that returns the prvious day inventory for each record and that is most likely the cause of my error. I found a possible solution with adding SELECT * FROM at the beginning of my code but i get a Syntax error when i do that and i'm not sure how to solve this problem.
here's my code
SELECT Stations.StationName, Product.ProductName, GasInventoryTransactions.TransactionDate, (SELECT TOP 1 Dupe.ActualInventory FROM GasInventory AS Dupe WHERE Dupe.StationID = Stations.StationID AND Dupe.ProductID = Product.ProductID AND Dupe.InventoryDate < GasInventory.InventoryDate ORDER BY Dupe.InventoryDate DESC) AS PreviousDayInventory, GasInventory.ActualInventory, GasInventoryTransactions.GasSales, GasInventoryTransactions.GasDelivery, [PreviousDayInventory]+[GasDelivery]-[GasSales] AS BookBalance, GasInventory.ActualInventory, [ActualInventory]-[BookBalance] AS OverShort
FROM (Stations INNER JOIN (Product INNER JOIN GasInventory ON Product.[ProductID] = GasInventory.[ProductID]) ON Stations.[StationID] = GasInventory.[StationID]) INNER JOIN GasInventoryTransactions ON GasInventory.[InventoryDate] = GasInventoryTransactions.[TransactionDate];
thanks for your help!
I'm having a little problem to convert this SQL query to JPQL:
select max(datePurchase) from purchases where userId = id and date_trunc('day',datePurchase)
in (select distinct (date_trunc('day',datePurchase)) as day from purchases where userId = id and datePurchase < initialDate and datePurchase > finalDate) group by date_trunc('day',datePurchase)
This sql is working well, that returns de last purchase per day made from a user. I tried to do the same, in JPQL:
Query query = em.createQuery("SELECT u MAX(u.datePurchase) FROM Purchases u WHERE u.userId.id = :id AND FUNC('day',u.datePurchase)" +
"IN (SELECT DISTINCT (FUNC('day',u.datePurchase)) AS day FROM Purchases WHERE u.userId.id = :id AND u.datePurchase < :finalDate AND u.datePurchase > :inicialDate) GROUP BY FUNC('day',u.datePurchase)");
query.setParameter("id", idUsuario);
query.setParameter("dataInicial", dataInicial);
query.setParameter("dataFinal", dataFinal);
List<MovSaldo> saldos = (List<MovSaldo>) query.getResultList();
em.getTransaction().commit();
The errors are:
"The IN expression does not have a valid expression." "An identification variable must be provided for a range variable declaration."
Probably is not something very difficult, but i have already spent a little frustrating time in it. Can someone please help me?
Although the answer is probably late for you I still posted it because it might help someone in the future.
In the nested select you have to put an identifier for the entity you are working with: FROM Purchases p and update things like (FUNC('day',u.datePurchase)) to (FUNC('day',p.datePurchase))
Best!
In my app a Position has_many Questions. In my position edit view, I create a set of checkboxes by looping over an array of Questions and checking those that the current position already includes.
Looks like this:
- #questions.each do |question|
= check_box_tag :question_ids, question.id, #position.questions.include?(question), name: 'position[question_ids][]', id: "question_check_#{question.id}"
= label_tag "question_check_#{question.id}", question.text
I noticed loading this page took an unusually long time and my logs had these (I've snipped it for space):
LOG: duration: 827.370 ms statement: SELECT 1 FROM "questions" INNER JOIN "required_questions" ON "questions"."id" = "required_questions"."question_id" WHERE "required_questions"."position_id" IS NULL AND "questions"."id" = 1 ORDER BY account_id desc, "questions".id asc LIMIT 1
LOG: duration: 821.666 ms statement: SELECT 1 FROM "questions" INNER JOIN "required_questions" ON "questions"."id" = "required_questions"."question_id" WHERE "required_questions"."position_id" IS NULL AND "questions"."id" = 2 ORDER BY account_id desc, "questions".id asc LIMIT 1
LOG: duration: 713.379 ms statement: SELECT 1 FROM "questions" INNER JOIN "required_questions" ON "questions"."id" = "required_questions"."question_id" WHERE "required_questions"."position_id" IS NULL AND "questions"."id" = 3 ORDER BY account_id desc, "questions".id asc LIMIT 1
I tracked the problem to this code:
#position.questions.include?(question)
I thought this was a simple Array.include? check so I was surprised by my findings. I was also surprised when I fixed it by adding an explicit .to_a call:
#position.questions.to_a.include?(question)
I was surprised a third time when I tested the original code in the Rails console and no SQL query was generated.
At this point I'm just curious - why did my original code generate a SQL query for each iteration when the same code in Rails console (albeit without the iteration and inside Rails console) did not? Why didn't it just do an Array.include? check?
This happens because #position.questions is not an array. It's actually an ActiveRecord::Relation. The problem is that the console actually behaves differently from your server application.
For example, in your console position.questions returns an array. That is because the console is actually evaluating this expression as position.questions.all which is equivalent to position.questions.to_a. In your server application the to_a or all is not called until you actually use the query. This is a good thing because it means you can continue to build up a query and it will only actually get executed when it's called.
For instance:
query = #position.questions
query.first
query.last
Will actually generate two queries that return two records in your server application because the query variable will be assigned an ActiveRecord::Relation instead of an Array. In your console this will generate a single query, but the query will load all of the questions into an Array and assign that to query and then select the first and last elements.
The all, first, last, count and even include? keywords are all triggers that actually execute the query, so in your application when you call #position.questions.include? you are executing a single query on the #position.questions relation. Adding the to_a causes this query to be executed immediately.
I have a PHP page running in postgres. I have 3 tables - workorders, wo_parts and part2vendor. I am trying to multiply 2 table column row datas together, ie wo_parts has a field called qty and part2vendor has a field called cost. These 2 are joined by wo_parts.pn and part2vendor.pn. I have created a query like this:
$scoreCostQuery = "SELECT SUM(part2vendor.cost*wo_parts.qty) as total_score
FROM part2vendor
INNER JOIN wo_parts
ON (wo_parts.pn=part2vendor.pn)
WHERE workorder=$workorder";
But if I add the costs of the parts multiplied by the qauntities supplied, it adds to a different number than what the script is doing. Help....I am new to this but if someone can show me in SQL I can modify it for postgres. Thanks
Without seeing example data, there's no way for us to know why you're query totals are coming out differently that when you do the math by hand. It could be a bad join, so you are getting more/less records than you expected. It's also possible that your calculations are off. Pick an example with the smallest number of associated records & compare.
My suggestion is to add a GROUP BY to the query:
SELECT SUM(p.cost * wp.qty) as total_score
FROM part2vendor p
JOIN wo_parts wp ON wp.pn = p.pn
WHERE workorder = $workorder
GROUP BY workorder
FYI: MySQL was designed to allow flexibility in the GROUP BY, while no other db I've used does - it's a source of numerous questions on SO "why does this work in MySQL when it doesn't work on db x...".
To Check that your Quantities are correct:
SELECT wp.qty,
p.cost
FROM WO_PARTS wp
JOIN PART2VENDOR p ON p.pn = wp.pn
WHERE p.workorder = $workorder
Check that the numbers are correct for a given order.
You could try a sub-query instead.
(Note, I don't have a Postgres installation to test this on so consider this more like pseudo code than a working example... It does work in MySQL tho)
SELECT
SUM(p.`score`) AS 'total_score'
FROM part2vendor AS p2v
INNER JOIN (
SELECT pn, cost * qty AS `score`
FROM wo_parts
) AS p
ON p.pn = p2v.pn
WHERE p2n.workorder=$workorder"
In the question, you say the cost column is in part2vendor, but in the query you reference wo_parts.cost. If the wo_parts table has its own cost column, that's the source of the problem.