Select Max Row from Column - sql

I have scan codes used in a table, but the table doesn't save just the newest scan codes. So I have order numbers with multiple items on those orders.
The issue is I need the last scan code on each item number for each order and not every time it has been scanned. Essentially I don't need to know that it has been scanned from prep to customization to shipping. I just need to know that it is in shipping. I get three results for one item number because it has been scanned three times.I don't need duplicate result from where it has been previously scanned.
The "S3DTNSEQ#" column is the number of times it has been scanned.I need to only keep the rows with the highest scan count. Anything lower than the highest scan count I need to get rid of. The 'Scan To' column is "S3DTSTO". So using the "S3DTNSEQ#" column to determine which row is kept is the idea.
SELECT
TMON as "order number",
TMCPO# as "po#",
TMRQD as "due date",
S3ITNO as "item number",
S3ORQT as "quantity",
TMCUST as "cust#",
TMNAME as, "cust name"
S3DTSTO as "scanned to",
TMSCHID as "sched id,
MAX( S3DTNSEQ# ) AS "S3DTNSEQ#",
S3DTADT as "maintained date"
FROM
TSA400.NRPDTA.SOP114F1 SOP114F1,
TSA400.NRPDTA.SOA SOA,
TSA400.NRPDTA.S3O S3O,
TSA400.NRPDTA.S3DTU S3DTU
WHERE SOP114F1.TMON = SOA.SOON
AND SOP114F1.TMSHP# = SOA.SOSHPN
AND SOP114F1.TMCUST = SOA.SOCUST
AND SOA.SOON = S3O.S3ON
AND SOP114F1.TMON = S3O.S3ON
AND SOA.SOCUST = S3O.S3CUST
AND SOP114F1.TMCUST = S3O.S3CUST
AND SOA.SOSHPN = S3O.S3SHPN
AND SOP114F1.TMON = S3DTU.S3DTON
AND SOP114F1.TMSHP# = S3DTU.S3DTSHP#
GROUP BY
TMON,
TMCPO#,
TMRQD,
S3ITNO,
S3ORQT,
TMCUST,
TMNAME,
S3DTSTO,
TMSCHID,
S3DTADT
I imagine I need a subquery to do this, but i am completely lost, on how to do this. I apologize, the query was created in "Showcase" which uses where clauses extensively instead of joins.

Related

SQL Join where is its own alias

Select IM_ITEM.ITEM_NO As "Item #",
IM_BARCOD.BARCOD AS "Barcode",
IM_INV.MIN_QTY AS "Min Qty"
FROM IM_ITEM
INNER JOIN IM_INV ON IM_INV.ITEM_NO = IM_ITEM.ITEM_NO
INNER JOIN IM_BARCOD ON IM_BARCOD.ITEM_NO = IM_ITEM.ITEM_NO
where IM_BARCOD.BARCOD_ID ='BIN#'
or IM_BARCOD.BARCOD_ID ='ITEM'
or IM_BARCOD.BARCOD_ID ='ALT1'
ORDER BY IM_ITEM.CATEG_SUBCAT ASC, IM_ITEM.ITEM_NO ASC;
This works great for me however it repeats the part number for every row there is more than one barcode. I want the different barcodes in their own column instead of having to duplicate the part number on every row there is a different barcode. ever better would be if it selected all barcodes and put them in their own column for that part number. Thanks for the help I am very new to any type of coding!

I have info on cycle counts in a warehouse that count the same locations multiple times. I want to get the latest NET_VAR for a specific location

I have used MAX(Date) and that will get me what i need until i put the qty in the mix, since they get different results after they fix things it has multiple answers and makes me group by the qty which in the end gives me multiple results. i just want the last count numbers.
SELECT (CH.MOD_DATE_TIME),LH.LOCN_BRCD ,DSP_SKU, (CH.ACTL_INVN_QTY-CH.EXPTD_QTY) "NET VAR" FROM CYCLE_COUNT_HIST CH , LOCN_HDR LH, ITEM_MASTER IM WHERE CH.WHSE = 'SH1' AND CH.LOCN_ID = LH.LOCN_ID AND CH.SKU_ID = IM.SKU_ID AND IM.CD_MASTER_ID = '147001' and DSP_SKU LIKE 'JBLBAR31BLKAM' AND LH.LOCN_BRCD = 'HAHK42A01' AND trunc(CH.CREATE_DATE_TIME) > SYSDATE-120
It returns 3 rows of results and I want the most recent line only. I plan to modify this to (select dsp_sku, sum(NET_VAR) in the end to run a summary of the sku.
I think you can use subquery.
You just need to put the following condition in where clause:
where .....
AND
CH.MOD_DATE_TIME = (select MAX( MOD_DATE_TIME)
from cycle_count_hist)

Calculate differences between two columns of two different tables

I want to calculate the difference between purchase order amount and purchase invoice amount. But I am not able to fetch the purchase invoice amount i.e. "pi.grand_total" and hence also not able to fetch the difference of "(pi.grand_total - po.grand_total)" . Please help.Below is my query.
PO = Purchase Order
PI = Purchase Invoice
SELECT DISTINCT
po.name AS "PO #:Link/Purchase Order:120",
po.supplier AS "Supplier:Link/Supplier:120",
po.Company AS "Company:Data:120",
po.currency AS "Currency:Link/Currency:120",
po.base_grand_total AS "Grand Total:Currency:120",
po.status AS "Status:Data:120",
po.per_received AS "Per Received:Data:120",
CEILING(po.per_billed) AS "Per Billed:Data:120",
po.delivery_date AS "Delivery Date:Date:120",
pi.grand_total AS "Final PI Total:120",
(pi.grand_total - po.grand_total) AS "Amount Difference:120"
FROM
"tabPurchase Order" as po
LEFT JOIN "tabPurchase Invoice" as pi ON po.name = pi.parent
WHERE
po.per_received = 100
AND
CEILING(po.per_billed) < 100
ORDER BY po.delivery_date ASC
You are using LEFT JOIN. This means when your second table has no data which matches with your first table you will receive no data from second table but nonetheless your first table will return all of its data.
You probably should check your join condition. If you wanted to join these two tables the way you want then use NVL Function for pi.grand_total column. Because it is on the left join it could have a NULL value thus NULL minus po.grand_total will give you NULL. NVL function turns NULL values into intended values like NVL(pi.grand_total,0)
A good example how joins work

What is the most efficient way to retrieve the single most recent record by date given certain other criteria

Given a table which has some fields as its composite key, along with a date, I need to find the record matching all fields except the date, which precedes the date. There is a unique index over all fields. There may be 1000+ records which match on the key, but I only need the one immediately preceding the date.
Previously, the system inserted a row on every day, so we could just access the record for date - 1 which is a direct lookup. However, this is leading to exponential growth in the database and cannot be continued (we are now over 500M rows and only really need ~700k of those).
As an example, this is a boiled-down version the current query:
select
i.quantity
from inventory i
where i.inventory_date = :inventory_date - 1
and i.company_id = :company_id
and i.client_id = :client_id
and i.product_id = :product_id;
And this is what I had intended to change it to. Unfortunately, the above query runs in linear time (single-row lookup on a unique index) whereas the below takes every row before doing the filtering (range scan on the unique index). In real world terms, we're talking hundreths of a second versus up to ten seconds.
select
quantity,
inventory_date
from (
select
i.quantity,
i.inventory_date,
max(i.inventory_date) over (partition by i.company_id, i.client_id, i.product_id) max_inv_date
from inventory i
where i.inventory_date < :inventory_date
and i.company_id = :company_id
and i.client_id = :client_id
and i.product_id = :product_id
)
where inventory_date = max_inv_date;
Is there a better (or at least, better-performing) way to write the above query?
For the first query:
select i.quantity
from inventory i
where i.inventory_date = :inventory_date - 1
and i.company_id = :company_id
and i.client_id = :client_id
and i.product_id = :product_id;
The best index is inventory(company_id, client_id, product_id, inventory_date, quantity). The first three elements of the index can be in a different order. And, other columns can be added after the date. For the index to be maximally useful, those three columns need to be first. "Linear" lookup time is not expected for this query and not needed.
To get the most recent value for date, keep the same index and do:
select i.*
from (select i.quantity
from inventory i
where i.company_id = :company_id and
i.client_id = :client_id and
i.product_id = :product_id and
i.inventory_date < :inventory_date
order by i.inventory_date desc
) i
where rownum = 1;

MySQL to return only last date / time record

We have a database that stores vehicle's gps position, date, time, vehicle identification, lat, long, speed, etc., every minute.
The following select pulls each vehicle position and info, but the problem is that returns the first record, and I need the last record (current position), based on date (datagps.Fecha) and time (datagps.Hora). This is the select:
SELECT configgps.Fichagps,
datacar.Ficha,
groups.Nombre,
datagps.Hora,
datagps.Fecha,
datagps.Velocidad,
datagps.Status,
datagps.Calleune,
datagps.Calletowo,
datagps.Temp,
datagps.Longitud,
datagps.Latitud,
datagps.Evento,
datagps.Direccion,
datagps.Provincia
FROM asigvehiculos
INNER JOIN datacar ON (asigvehiculos.Iddatacar = datacar.Id)
INNER JOIN configgps ON (datacar.Configgps = configgps.Id)
INNER JOIN clientdata ON (asigvehiculos.Idgroup = clientdata.group)
INNER JOIN groups ON (clientdata.group = groups.Id)
INNER JOIN datagps ON (configgps.Fichagps = datagps.Fichagps)
Group by Fichagps;
I need same result I'm getting, but instead of the older record I need the most recent
(LAST datagps.Fecha / datagps.Hora).
How can I accomplish this?
Add ORDER BY datagps.Fecha DESC, datagps.Hora DESC LIMIT 1 to your query.
I'm not sure why you are having any problems with this as Lex's answers seem good.
I would start putting ORDER BY's in your query so it puts them in an order, when it's showing the record you want as the first one in the list, then add the LIMIT.
If you want the most recent, then the following should be good enough:
ORDER BY datagps.Fecha DESC, datagps.Hora DESC
If you simply want the record that was added to the database most recently (irregardless of the date/time fields), then you could (assuming you have an auto-incremental primary key in the datagps table (I assume it's called dataID for this example)):
ORDER BY datagps.dataID DESC
If these aren't showing the data you want - then there is something missing from your example (maybe data-types aren't DATETIME fields? - if not - then maybe a CONVERT to change them from their current type before ORDERing BY would be a good idea)
EDIT:
I've seen the screenshot and I'm confused as to what the issue is still. That appears to be showing everything in order. Are you implying that there are many more than 5 records? How many are you expecting?
Do you mean: for each record returned, you want the one row from the table datagps with the latest date and time attached to the result? If so, how about this:
# To show how the query will be executed
# comment to return actual results
EXPLAIN
SELECT
configgps.Fichagps, datacar.Ficha, groups.Nombre, datagps.Hora, datagps.Fecha,
datagps.Velocidad, datagps.Status, datagps.Calleune, datagps.Calletowo,
datagps.Temp, datagps.Longitud, datagps.Latitud, datagps.Evento,
datagps.Direccion, datagps.Provincia
FROM asigvehiculos
INNER JOIN datacar ON (asigvehiculos.Iddatacar = datacar.Id)
INNER JOIN configgps ON (datacar.Configgps = configgps.Id)
INNER JOIN clientdata ON (asigvehiculos.Idgroup = clientdata.group)
INNER JOIN groups ON (clientdata.group = groups.Id)
INNER JOIN datagps ON (configgps.Fichagps = datagps.Fichagps)
########### Add this section
LEFT JOIN datagps b ON (
configgps.Fichagps = b.Fichagps
# wrong condition
#AND datagps.Hora < b.Hora
#AND datagps.Fecha < b.Fecha)
# might prevent indexes to be used
AND (datagps.Fecha < b.Fecha OR (datagps.Fecha = b.Fecha AND datagps.Hora < b.Hora))
WHERE b.Fichagps IS NULL
###########
Group by configgps.Fichagps;
Similar question here only that that one uses outer joins.
Edit (again):
The conditions are wrong so corrected it. Can you show us the output of the above EXPLAIN query so we can pinpoint where the bottle neck is?
As hurikhan77 said, it will be better if you could convert both of the the columns into a single datetime field - though I'm guessing this would not be possible for your case (since your database is already being used?)
Though if you can convert it, the condition (on the join) would become:
AND datagps.FechaHora < b.FechaHora
After that, add an index for datagps.FechaHora and the query would be fast(er).
What you probably want is getting the maximum of (Fecha,Hora) per grouped dataset? This is a little complicated to accomplish with your column types. You should combine Fecha and Hora into one column of type DATETIME. Then it's easy to just SELECT MAX(FechaHora) ... GROUP BY Fichagps.
It could have helped if you posted your table structure to understand the problem.