ORA-00904: "Q"."ITEM_NO": invalid identifier - Oracle SQL group by issue - sql

I have this query to fetch item no's and their quantities filtered by a specific unit.
select q.item_no, sum(q.quantity) from item_unit_quantity q
where q.unit_no = 'PH00000096' group by q.item_no
Now I want to add price column which I get from another two tables
There is a condition, Price is always the maximum of the latest three GRN dates.
select max(price) from (select price from grn_item gi join grn g on gi.grn_no = g.grn_no
where gi.item_no = 'IT00001896' order by g.grn_date desc) where rownum <= 3
When I combined the queries as below,
select q.item_no, sum(q.quantity),
(select max(price) from (select price from grn_item gi join grn g on gi.grn_no = g.grn_no
where gi.item_no = q.item_no order by g.grn_date desc) where rownum <= 3) "PRICE"
from item_unit_quantity q where q.unit_no = 'PH00000096' group by q.item_no
I get
ORA-00904: "Q"."ITEM_NO": invalid identifier
But if I change the above as "gi.item_no = 'IT00001896'" I get
ITEM_NO | Sum(Quantity) | Price
--------------------------------------
IT00012824 | 14 | 3.68
IT00006345 | 494 | 3.68
IT00001896 | 5 | 3.68
I still want to display the Item no, Item quantity and price for each Item no in this query, how can I do this?

Your question is a bit hard to follow without sample data. However, subqueries with GROUP BY can be finicky. A simple solution is to move the subquery to the FROM clause:
select q.item_no, sum(q.quantity), max(max_price)
from item_unit_quantity q left join
(select gi.item_no, max(g.price) as max_price
from grn_item gi join
grn g
on gi.grn_no = g.grn_no
group by gi.item_no
) gi
on gi.item_no = q.item_no
where q.unit_no = 'PH00000096'
group by q.item_no

Related

How to get Odoo Inventory adjustment value through SQL

I am working on a custom stock valuation module and in one model I am trying to get adjustment value for a lot - product - warehouse wise of the previous day.
QUERY 1
SELECT COUNT(*)
FROM
(
SELECT stock_inventory.date AS stock_adjustment_date,
stock_move_line.lot_id,
stock_move_line.product_id,
SUM(stock_move_line.qty_done) total_stock_adjustment
FROM stock_move_line
LEFT JOIN stock_move ON stock_move_line.move_id = stock_move.id
LEFT JOIN stock_inventory ON stock_move.inventory_id = stock_inventory.id
WHERE stock_move.inventory_id IS NOT NULL
AND stock_move_line.location_id = 5
AND stock_move_line.location_dest_id = 13
AND stock_move_line.lot_id IS NOT NULL
GROUP BY stock_move_line.lot_id, stock_move_line.product_id, stock_inventory.date
ORDER BY total_stock_adjustment DESC
)
testTable;
QUERY 2
SELECT COUNT(*)
FROM
(
SELECT stock_inventory.date AS stock_adjustment_date,
stock_move_line.lot_id,
stock_move_line.product_id,
SUM(stock_move_line.qty_done) total_stock_adjustment
FROM stock_move_line
LEFT JOIN stock_move ON stock_move_line.move_id = stock_move.id
LEFT JOIN stock_inventory ON stock_move.inventory_id = stock_inventory.id
WHERE stock_move.inventory_id IS NOT NULL
AND stock_move_line.location_id = 13
AND stock_move_line.location_dest_id = 5
AND stock_move_line.lot_id IS NOT NULL
GROUP BY stock_move_line.lot_id, stock_move_line.product_id, stock_inventory.date
ORDER BY total_stock_adjustment DESC
)
testTable;
Why these both queries returning same count 14,849 ?
13 is the warehouse ID and 5 is the virtual location used for adjustment. What I am doing wrong here?

I have a SUM function in my SELECT but don't want it to show

I want to see the companies which deliver the most sold items in my DB.
Currently i have this Code:
SELECT L."Firma", SUM("B"."Anzahl")
FROM "Bestelldetails" B, "Artikel" A, "Lieferanten" L
WHERE L."Lieferanten-Nr" = A."Lieferanten-Nr"
AND A."Artikel-Nr" = B."Artikel-Nr"
GROUP BY L."Firma"
ORDER BY 2 DESC
The Output that i get:
Firma
2
Company 1
2756
Company 2
2377
Company 3
2063
...many more...
..XXX..
The Output that i want:
Firma
Company 1
Company 2
Company 3
...many more...
Code with output as image
But i don't want the row with the number 2 to show. I just want the Company-Names to show. How would i do so?
Simply ORDER BY the SUM():
SELECT L."Firma"
FROM "Bestelldetails" B
JOIN "Artikel" A
ON A."Artikel-Nr" = B."Artikel-Nr"
JOIN "Lieferanten" L
ON L."Lieferanten-Nr" = A."Lieferanten-Nr"
GROUP BY L."Firma"
ORDER BY SUM("B"."Anzahl") DESC
(Now using proper, explicit JOIN syntax.)
select Firma from
(
SELECT L."Firma", SUM("B"."Anzahl")
FROM "Bestelldetails" B, "Artikel" A, "Lieferanten" L
WHERE L."Lieferanten-Nr" = A."Lieferanten-Nr"
AND A."Artikel-Nr" = B."Artikel-Nr"
GROUP BY L."Firma"
ORDER BY 2 DESC
);

Can't order query correctly

A while ago I requested help to code a LEFT JOIN filtering in a particular way that the result postition the desired value in the first row.
Need to retrieve table's last inserted/updated record with some exclusions
The thing now is that there are many cases which are mixing data. The scenario is that on the same table we have 2 values that we need to organize on different columns. The PO_ID is unique, but can have 1 or more values on the other tables, and for this particular case 1 PO_ID has 3 SHIP_ID_CUS values. We only need 1 PO_ID per row (no duplicates) that is way we used the MAX() and GROUP BY.
Here is a piece of the code that I think cause issues.
select
z.po_id,
max(scdc.ship_id) as ship_id_cdc,
max(lscdc.ship_evnt_cd) as last_event_cdc,
max(lscdc.ship_evnt_tms) as event_tms_cdc,
max(scus.SHIP_ID) as ship_id_cus,
max(lscus.ship_evnt_cd) as last_event_cus,
max(lscus.ship_evnt_tms) as event_tms_cus
from TABLE.A z
left join (select distinct po_id, iltc.ship_id, s.ship_to_loc_code from TABLE.B iltc inner join TABLE.C s on iltc.ship_id=s.ship_id and iltc.ship_to_loc_code=s.ship_to_loc_code and s.ship_to_ctry<>' ') AS A ON z.po_id = a.po_id
left JOIN TABLE.C scus ON A.SHIP_ID = scus.SHIP_ID AND A.SHIP_TO_LOC_CODE = scus.SHIP_TO_LOC_CODE and scus.loc_type = 'CUS' AND DAYS(scus.shipment_tms)+10 >= DAYS(z.ship_tms)
left JOIN TABLE.C scdc ON A.SHIP_ID = scdc.SHIP_ID AND A.SHIP_TO_LOC_CODE = scdc.SHIP_TO_LOC_CODE and scdc.loc_type = 'CDC' AND DAYS(scdc.shipment_tms)+10 >= DAYS(z.ship_tms)
left join
( select ship_id_856, ship_to_loc_cd856, ship_evnt_cd, ship_evnt_tms, carr_tracking_num, event_srv_lvl
, row_number() over(partition by ship_id order by updt_job_tms desc) as RN
FROM TABLE.D
WHERE LEFT(ship_evnt_cd, 1) <> '9') lscus
ON lscus.ship_id_856=scus.ship_id and scus.ship_to_loc_code=lscus.ship_to_loc_cd856 and lscus.rn = 1
left join
( select ship_id_856, ship_to_loc_cd856, ship_evnt_cd, ship_evnt_tms, carr_tracking_num, event_srv_lvl
, row_number() over(partition by ship_id order by updt_job_tms desc) as RN
FROM TABLE.D
WHERE LEFT(ship_evnt_cd, 1) <> '9') lscdc
ON lscdc.ship_id_856=scdc.ship_id and lscdc.ship_to_loc_cd856=scdc.ship_to_loc_code and lscdc.rn = 1
WHERE
z.po_id = 'T1DLDC'
GROUP BY z.po_id
By searching that condition we get the following result
The problem is that if we search directly on the TABLE.D, the last event that we need (with last update record tms) is another one (X1) and somehow the date is incorrect.
What is even more weird, is that if we search for the ship_id_cus on the original query, we get the correct code but still with a wrong date...
WHERE
--z.po_id = 'T1DLDC'
scus.ship_id = 'D30980'
GROUP BY z.po_id
I tried other logic changes like modifying the left joins to search on a subquery.
left JOIN ( select * from TABLE.C order by updt_job_tms desc) scus ON A.SHIP_ID = scus.SHIP_ID AND A.SHIP_TO_LOC_CODE = scus.SHIP_TO_LOC_CODE and scus.loc_type = 'CUS' AND DAYS(scus.shipment_tms)+10 >= DAYS(z.ship_tms)
But this is also giving the same exact results by searching either by po_id or ship_id_cus
Any ideas or comment will be much appreciated.
Thanks
------------------------------------UPDATE-----------------------------------
Adding the result of the LEFT JOIN with the row_partition() including all the ship_id_cus for that po_id, and all the codes with the tms. None match here.
Based on all these, it should be the last ship_id_cus with X1 event/tms. If we exclude also the ones starting with 9, we would get the following result.
(I am not applying here ordering by ship_id_cus, which already described before that did not work either the way I implemented)
If you have a table: TBL1
ID APPROVED APPROVER DATE_APPROVED
====== ======== ======== =============
ABC Y JOE 2019-01-13
ABC N ZACK 2018-12-23
ABC N SUE 2019-02-23
And you do SQL:
SELECT ID, MAX(APPROVED) AS APPROVAL
,MAX(APPROVER) AS APPROVED_BY , MAX(DATE_APPROVED) AS APPROVED_ON
FROM TBL1 GROUP BY ID
you will get result:
ID APPROVAL APPROVED_BY APPROVED_ON
====== ======== =========== =============
ABC Y ZACK 2019-02-23
which is correct to the code but is NOT what you want
Try the following:
SELECT T1.ID, T1.APPROVED, T1.APPROVER, T1.DATE_APPROVED
FROM TBL1 AS T1
INNER JOIN (SELECT ID, MAX(DATE_APPROVED) AS APPROVED_ON
FROM TBL1 GROUP BY ID
) AS T2
ON T1.ID =T2.ID
AND T1.DATE_APPROVED = T2.APPROVED_ON
Result:
ID APPROVED APPROVER DATE_APPROVED
====== ======== ======== =============
ABC N SUE 2019-02-23

Combining data into a single cell while summing a seperate cell

I don't know how to word my question very well, so I will start with the data being returned:
prop_id | assessed_value | sale_id
35004 | 401200 | 1920831
35005 | 40500 | 1920831
35023 | 11300 | 1920831
34380 | 139100 | 1915846
127959 | 286400 | 1915882
I would like it to return:
prop_id | assessed_value | sale_id
35004, 35005, 35023 | 453000(Sum of the 3 parcels) | 1920831
34380 | 139100 | 1915846
127959 | 286400 | 1915882
So my main goal is to combine all the parcels on the sale_id field into a string, but only when a sale id has multiple prop_id, and then sum up the assessed value of all those. This is the query I am using to get the first set of data...
select
pv1.[prop_id],
pv1.[assessed_val],
ld1.[sale_id]
from dbo.land_detail as ld1
join dbo.property_val as pv1 on
pv1.[prop_id] = ld1.[prop_id] and
pv1.[prop_val_yr] = ld1.[prop_val_yr] and
pv1.[sup_num] = ld1.[sup_num]
left join dbo.sale as sale1 on
sale1.[chg_of_owner_id] = ld1.[sale_id]
where
pv1.[prop_inactive_dt] is null
order by sale_id, prop_id
prop_id is of data type INT
assessed_val is of data type numeric(14,0)
sale_id is of data type INT
You can use WITH to create a temporary table then you can use STUFF() FOR XML PATH to concatenate the prop_id field into one row
WITH temp AS (
select pv1.[prop_id],
pv1.[assessed_val],
ld1.[sale_id],
sale1.[sl_price],
sale1.[sl_dt],
(pv1.[assessed_val]/NULLIF(sale1.[sl_price],0) as Ratio
from dbo.land_detail as ld1 with(nolock)
join dbo.property_val as pv1 with(nolock)
on pv1.[prop_id] = ld1.[prop_id]
and pv1.[prop_val_yr] = ld1.[prop_val_yr]
and pv1.[sup_num] = ld1.[sup_num]
left join dbo.sale as sale1 with(nolock)
on sale1.[chg_of_owner_id] = ld1.[sale_id]
where sale1.sl_dt <= '04/30/16'
and sale1.sl_dt >= '05/01/15'
and pv1.[sub_type] = 'r'
and pv1.[prop_val_yr] = 2016
and pv1.[prop_inactive_dt] is null
order by sale_id, prop_id
)
SELECT STUFF(( SELECT ', ' + CAST(prop_id AS VARCHAR)
FROM temp
WHERE sale_id = t.sale_id
FOR XML PATH(''),TYPE)
.value('.','NVARCHAR(MAX)'),1,2,'') AS parcels,
SUM(t.assessed_val) assessed_val,
t.sale_id,
t.sl_price,
t.sl_dt,
SUM(t.ratio) ratio
FROM temp t
GROUP BY t.sale_id,
t.sl_price,
t.sl_dt
ORDER BY t.sale_id DESC
Put everything into a temp table (#temp) as below. Then make a self join to select the values. There are several ways of doing concatenation using (SUFF(), XML PATH, etc). Search on the internet on how to concatenate rows into comma separated string refer to this link for example
select
pv1.[prop_id],
pv1.[assessed_val],
ld1.[sale_id],
sale1.[sl_price],
sale1.[sl_dt],
(pv1.[assessed_val]/sale1.[sl_price]) as Ratio
--------Temp Table------------
INTO #temp
------------------------------
from dbo.land_detail as ld1 with(nolock)
join dbo.property_val as pv1 with(nolock) on
pv1.[prop_id] = ld1.[prop_id] and
pv1.[prop_val_yr] = ld1.[prop_val_yr] and
pv1.[sup_num] = ld1.[sup_num]
left join dbo.sale as sale1 with(nolock) on
sale1.[chg_of_owner_id] = ld1.[sale_id]
where
sale1.sl_dt <= '04/30/16' and
sale1.sl_dt >= '05/01/15' and
pv1.[sub_type] = 'r' and
pv1.[prop_val_yr] = 2016 and
pv1.[prop_inactive_dt] is null
order by sale_id, prop_id

How to us Group By in SQL with a JOIN

I am wondering if anyone could help me. I trying to write a query which will group all the order detail lines to each product.
SELECT
Line.NetAmount, Line.QtyDespatch, Line.QtyOrder,
Line.Price, Line.Price * Line.QtySent AS 'Value'
FROM dbo.orderdetails line
LEFT JOIN
(
SELECT products.ProductID, products.CompanyID AS StockCompanyID,
products.StockCode FROM dbo.products
)
Stock ON Line.ProductID = products.ProductID AND products.StockCompanyID = Line.CompanyID
WHERE Line.CompanyID = 1
ORDER BY Stock.StockID ASC
The results I am getting are for each order details line individually but I want to group-by the each product id and have (Line.Price * Line.QtySent) as sum for each product and show each product once.
The result I am getting are
PID Net sent qty Price Value
39044 12 0 5 2.4 0
39044 12 0 5 2.4 0
39044 12 0 5 2.4 0
39044 12 0 5 2.4 0
But I do not want to get it for each line but a cumulative value for all line by product. Basically cumulative totals for each product
You would need to group by the ProductId and then sum the Line.Price multiplied by the Line.QtySent. You would want something like this:
SELECT p.ProductID, SUM(Line.Price * Line.QtySent) AS 'Value'
FROM dbo.orderdetails line
LEFT JOIN dbo.products p ON
Line.ProductID = p.ProductID AND p.CompanyID = Line.CompanyID
WHERE Line.CompanyID = 1
GROUP BY p.ProductID
Your description sounds like this query:
SELECT od.ProductId, SUM(od.Price * od.QtySent) as total
FROM dbo.orderdetails od
GROUP BY od.ProductId;