SQL Most recently updated row - sql

I am pulling information from an SQL database but it displays all lines various times because of multiple updates.
i have managed to eliminate duplicate using the distinct function however still shows multiple lines for the changes.
i.e.
original Qty = 4
update 1 Qty = 5
update 2 Qty = 6
All i want is the most recent update each line which is column OLLNID
SELECT DISTINCT
OLMCU,
OLKCOO,
OLDOCO,
OLDCTO,
Date( OLTRDJ, CYYDDD ) AS OLTRDJ,
OLLNID AS OLLNID_1,
OLDSC1,
OLDSC2 AS OLDSC2_1,
OLUOM,
OLUORG,
OLPRRC,
OLAEXP,
OLANBY
FROM
E1PDES01.PRODDTA.F43199 F43199
WHERE
OLMCU = '13248'
AND Date( OLTRDJ, CYYDDD ) >= '01/01/2017'
AND OLDCTO = 'OP'
AND OLDOCO = 13484379
ORDER BY
6

Like subkonstrukt I am guessing what you really want.
In case that you want the latest results by OLLNID (which is then e.g. a date), then you could group by all other values (when they differ) and choose the max OLLNID.
SELECT
OLMCU,
OLKCOO,
OLDOCO,
OLDCTO,
Date(OLTRDJ, CYYDDD) AS OLTRDJ,
MAX(OLLNID) AS OLLNID_1,
OLDSC1,
OLDSC2 AS OLDSC2_1,
OLUOM,
OLUORG,
OLPRRC,
OLAEXP,
OLANBY
FROM E1PDES01.PRODDTA.F43199 F43199
WHERE OLMCU = '13248'
AND Date(OLTRDJ, CYYDDD) >= '01/01/2017'
AND OLDCTO = 'OP'
AND OLDOCO = 13484379
GROUP BY
OLMCU,
OLKCOO,
OLDOCO,
OLDCTO,
OLTRDJ,
OLDSC1,
OLDSC2,
OLUOM,
OLUORG,
OLPRRC,
OLAEXP,
OLANBY;

depending on what SQL Flavor you´re using this might not work, also I am made some wild assumptions on your data so if you could supply more information (maybe schema / types, SQL Flavor, maybe two or three dummy rows) I will edit my answer
SELECT
org.OLMCU,
org.OLKCOO,
org.OLDOCO,
org.OLDCTO,
Date(org.OLTRDJ, CYYDDD ) AS OLTRDJ,
org.OLLNID AS OLLNID_1,
org.OLDSC1,
org.OLDSC2 AS OLDSC2_1,
org.OLUOM,
org.OLUORG,
org.OLPRRC,
org.OLAEXP,
org.OLANBY
FROM
E1PDES01.PRODDTA.F43199 F43199 as org
LEFT OUTER JOIN E1PDES01.PRODDTA.F43199 F43199 aux ON org.OLLNID = aux.OLLNID AND org.OLLNID < aux.OLLNID
WHERE
org.OLMCU = '13248'
AND Date( org.OLTRDJ, CYYDDD ) >= '01/01/2017'
AND org.OLDCTO = 'OP'
AND org.OLDOCO = 13484379
AND aux.OLLNID IS NULL
GROUP BY
org.OLMCU,
org.OLKCOO,
org.OLDOCO,
org.OLDCTO,
Date(org.OLTRDJ, CYYDDD ) AS OLTRDJ,
org.OLLNID AS OLLNID_1,
org.OLDSC1,
org.OLDSC2 AS OLDSC2_1,
org.OLUOM,
org.OLUORG,
org.OLPRRC,
org.OLAEXP,
org.OLANBY
ORDER BY org.OLLNID

Related

SQL Query to Find if (Count of date > X) = 0 For Group of ID

I apologize if the title is not be correct as I'm not sure what I need to ask for, since I don't know how to build the query.
I have the following query built to return a list of chemicals and other related fields.
SELECT DISTINCT
RDB.Chemical_Record.[Chemical_ID],
RDB.Chemical_Record.[Expires_Date],
RDB.Assay_Group.[Assay_Group_Name] AS [Assay Group],
RDB.Chemical.[Chemical_Name],
RDB.Chemical.[Product_Number],
RDB.Chemical_Record.[Lot_Number],
RDB.Storage_Location.[Location_Name]
FROM RDB.Chemical_Record
LEFT JOIN RDB.Chemical ON Chemical_Record.[Chemical_ID] = Chemical.[ID_Chemical]
LEFT JOIN RDB.Storage_Location ON Storage_Location.[ID_Storage_Location] = Chemical_Record.[Storage_Location_ID]
LEFT JOIN RDB.Chemical_To_AGroup ON Chemical_To_AGroup.[Chemical_ID] = Chemical_Record.[Chemical_ID]
LEFT JOIN RDB.Assay_Group ON Assay_Group.[ID_Assay_Group] = Chemical_To_AGroup.[Assay_Group_ID]
WHERE RDB.Chemical_Record.[Expires_Date] >= DATEADD(day,-60, GETDATE())
ORDER BY RDB.Chemical_Record.[Chemical_ID], RDB.Chemical_Record.[Expires_Date], RDB.Assay_Group.[Assay_Group_Name]
I am using this query in a VB.Net application where it exports the results to an Excel worksheet and then performs additional actions to delete the rows I don't need. The process to query is quick, but working with Excel from .Net is painful and slow.
Instead I'd like to build the query to return the exact results I want, which I think is possible, I just can't figure out how. I have tried using a combination of Count, Group and Having, but since I've never worked with those I can't get them to work for me.
Example:
SELECT
COUNT(RDB.Chemical_Record.[Chemical_ID]) Count_ID,
RDB.Chemical_Record.[Chemical_ID],
RDB.Chemical_Record.[Expires_Date]
FROM RDB.Chemical_Record
WHERE RDB.Chemical_Record.[Expires_Date] > DATEADD(day,30,GETDATE())
GROUP BY RDB.Chemical_Record.[Chemical_ID], RDB.Chemical_Record.[Expires_Date]
ORDER BY RDB.Chemical_Record.[Chemical_ID]
As you can see from this example, it doesn't return the count of ID's where Expiration Date > DATEADD(day,30,GETDATE()) nor does it return the ID's that I actually wanted.
What I need to return is all chemicals (ID) that DO NOT have an expiration date > Today + 30 for that specific ID. The screenshot below shows an example of the data that gets pulled. The yellow highlighted rows are the only two in that set that should get returned as there are no other chemicals of those two ID's with an expiration date > Today + 30. All the other ID's should not show up since they DO have ID's of COUNT(Expiration Date > Today + 30) > 0.
If someone could help me build the query using the appropriate Aggregate functions, it would be MUCH appreciated.
What I need to return is all chemicals (ID) that DO NOT have an expiration date > Today + 30 for that specific ID.
For this question, you can use a HAVING clause. No WHERE is needed:
SELECT COUNT(*) as Count_ID, cr.[Chemical_ID]
FROM RDB.Chemical_Record cr
GROUP BY cr.[Chemical_ID]
HAVING MAX(cr.Expires_Date) <= DATEADD(day, 30, GETDATE())
ORDER BY cr.[Chemical_ID]
Using the HAVING MAX solved my problem and I was then able to work out exactly what I needed. I had to do some more research to figure out how to bring all my columns back, but that wasn't as difficult.
Here is my final solution:
WITH CHEM AS (
SELECT RDB.Chemical_Record.[Chemical_ID]
FROM RDB.Chemical_Record
GROUP BY RDB.Chemical_Record.[Chemical_ID]
HAVING MAX(RDB.Chemical_Record.Expires_Date) <= DATEADD(day, 60, GETDATE())
)
SELECT DISTINCT
RDB.Chemical_Record.[Chemical_ID],
RDB.Chemical_Record.[Expires_Date],
RDB.Assay_Group.[Assay_Group_Name] AS [Assay Group],
RDB.Chemical.[Chemical_Name],
RDB.Chemical.[Product_Number],
RDB.Chemical_Record.[Lot_Number],
RDB.Storage_Location.[Location_Name]
FROM RDB.Chemical_Record
INNER JOIN CHEM ON CHEM.Chemical_ID = RDB.Chemical_Record.Chemical_ID
LEFT JOIN RDB.Chemical ON Chemical_Record.[Chemical_ID] = Chemical.[ID_Chemical]
LEFT JOIN RDB.Storage_Location ON Storage_Location.[ID_Storage_Location] = Chemical_Record.[Storage_Location_ID]
LEFT JOIN RDB.Chemical_To_AGroup ON Chemical_To_AGroup.[Chemical_ID] = Chemical_Record.[Chemical_ID]
LEFT JOIN RDB.Assay_Group ON Assay_Group.[ID_Assay_Group] = Chemical_To_AGroup.[Assay_Group_ID]
WHERE Expires_Date >= DATEADD(day, -60, GETDATE())
ORDER BY RDB.Chemical_Record.[Chemical_ID], RDB.Chemical_Record.Expires_Date
And a screenshot showing the resulting search:

How can I use sql db2 update function?

I have a sql db2 code that get information on a existing data table and I want to modify it to not download the data starting from 2020-02-01, instead just update this table everyday. Please help me to modify this script not to retrieve the whole data over and over again just to update but keeps on updating only the new data everyday.
create table public.fc_TDPMean_By_DIM2_EtchDate as
select DIM2_EtchDate, Model, tool_id, avg(TDPower) as TDPower_Mean, count(slider_id)
from (select distinct a.slider_id, trunc(a.test_date_time), left(a.product_id,2) as Model, a.wafer_id, a.row_number,
a.column_number, a.x_coordinate, a.y_coordinate, a.error_code, a.grade, a.bin,
a.TFCTDPWR as TDPower, b.job_number, trunc(c.transaction_date_time) as DIM2_EtchDate, c.tool_id
from ah.param_jade_wide a left join ah.param_lap_summary b on a.wafer_id = b.wafer_id and a.row_number = b.row_number
left join ah.his_job c on c.job_number = b.job_number
where c.transaction_date_time > '2020-02-01'
and left(a.product_id,2) in ('L2','L3','L8','C3','C2','V8')
and b.source_system_code in ('MFG2.SLDR.LAPRUN')
and c.operation_id in ('545600')
and a.retest_number = 0
and a.class_description in ('PROD')
and not c.tool_id = 0 and not c.tool_id in ('') )
group by DIM2_EtchDate, Model, tool_id;
commit;
As You want to add a new "day" entry/entries every day (as DIM2_EtchDate == DATE(c.transaction_date_time) is a part of the summary table), and if You are OK with not selecting "today's" entries, You can just use a simple INSERT for "yesterdays and before" entries, run every day like this:
INSERT INTO public.fc_TDPMean_By_DIM2_EtchDate
SELECT DIM2_EtchDate, Model, tool_id, avg(TDPower) AS TDPower_Mean, count(slider_id)
FROM (SELECT DISTINCT a.slider_id, LEFT(a.product_id,2) as Model,
a.TFCTDPWR AS TDPower, TRUNC(c.transaction_date_time) as DIM2_EtchDate, c.tool_id
-- (I got rid of not used columns.)
FROM ah.param_jade_wide a
LEFT JOIN ah.param_lap_summary b ON (a.wafer_id, a.row_number) = (b.wafer_id, b.row_number)
LEFT JOIN ah.his_job c ON c.job_number = b.job_number
WHERE c.transaction_date_time > '2020-02-01' --MAX(DIM2_EtchDate)
AND c.transaction_date_time < CURRENT DATE
AND LEFT(a.product_id,2) IN ('L2','L3','L8','C3','C2','V8')
AND b.source_system_code IN ('MFG2.SLDR.LAPRUN')
AND c.operation_id IN ('545600')
AND a.retest_number = 0
AND a.class_description IN ('PROD')
AND NOT c.tool_id = 0 AND NOT c.tool_id in ('')
)
GROUP BY DIM2_EtchDate, Model, tool_id
-- WITH appropriate isolation
;
(I haven't tested it. This should work if c.transaction_date_time is DATE. If it is TIMESTAMP, then c.transaction_date_time > '2020-02-01' changes to c.transaction_date_time >= TIMESTAMP('2020-02-01', '00:00') + 1 DAY.)
If You would want to update it more often than once per day, having also incomplete data for today, it could be done using MERGE. If so, just tell me, I could manage to write a MERGE for it. (Or You could, that would be better.)

Joining WIP_DISCRETE_JOBS to a Bill Of Materials table

I have an SQL query in which I am trying to fetch items along with their components which have Bill Of Materials (BOM) enabled and whose creation date is withing the last three years.
The problem is every item along with their component list gets repeated. Suppose an item has 5 components, and I query with the particular item number. I get 35 rows (7 repetitions of sets of 5 components). However, if I query with a particular WIP_ENTITY_NAME or if I use DISTINCT, I get a perfect 5 rows of data. I need to get this data (5 rows, no repetitions) when I query with a particular item number.
Here is the query:
SELECT *
FROM BOM_BILL_OF_MATERIALS BOM,
BOM_INVENTORY_COMPONENTS BIC,
BOM_COMPONENTS_B BCB,
BOM_OPERATIONAL_ROUTINGS_V BORV,
BOM_OPERATION_SEQUENCES_V BOSV,
BOM_STRUCTURES_B BSB,
BOM_STRUCTURE_TYPES_B BST,
MTL_SYSTEM_ITEMS_B MSI,
MTL_SYSTEM_ITEMS_TL MSIT,
ORG_ORGANIZATION_DEFINITIONS OOD,
WIP_DISCRETE_JOBS_V WDJV
WHERE BOM.BILL_SEQUENCE_ID = BIC.BILL_SEQUENCE_ID
AND BIC.COMPONENT_SEQUENCE_ID = BCB.COMPONENT_SEQUENCE_ID
AND BCB.BILL_SEQUENCE_ID = BSB.BILL_SEQUENCE_ID
AND BOM.STRUCTURE_TYPE_ID = BST.STRUCTURE_TYPE_ID
AND BOM.ASSEMBLY_ITEM_ID = MSI.INVENTORY_ITEM_ID
AND BOM.ORGANIZATION_ID = MSI.ORGANIZATION_ID
AND BOSV.ROUTING_SEQUENCE_ID = BORV.ROUTING_SEQUENCE_ID
AND BORV.ASSEMBLY_ITEM_ID = BOM.ASSEMBLY_ITEM_ID
AND BORV.ORGANIZATION_ID = BOM.ORGANIZATION_ID
AND MSI.INVENTORY_ITEM_ID = MSIT.INVENTORY_ITEM_ID
AND MSI.ORGANIZATION_ID = MSIT.ORGANIZATION_ID
AND MSIT.ORGANIZATION_ID = OOD.ORGANIZATION_ID
AND MSIT.LANGUAGE = USERENV('LANG')
AND sysdate BETWEEN BCB.EFFECTIVITY_DATE AND NVL(BCB.DISABLE_DATE, sysdate)
AND MSI.BOM_ENABLED_FLAG = 'Y'
AND NVL(MSI.ENABLED_FLAG,'X') ='Y'
AND OOD.ORGANIZATION_ID IN (203,204,328)
AND BORV.COMMON_ROUTING_SEQUENCE_ID = WDJV.COMMON_ROUTING_SEQUENCE_ID
AND BORV.ASSEMBLY_ITEM_ID = WDJV.PRIMARY_ITEM_ID
AND WDJV.CREATION_DATE > ADD_MONTHS( sysdate, -12*3 )
AND WDJV.WIP_ENTITY_NAME = '28799'
--and MSI.SEGMENT1='9064090'
Also, I have found that the sets of 5 differ from each other on the basis of their WE_ROW_ID, REQUEST_ID_7, SCHEDULED_START_DATE, SCHEDULED_COMPLETION_DATE and other columns which are present in the WIP_DISCREET_JOBS table. Is there any way to map these columns to any of the BOM tables? I am new to this, so please bear with me gurus.
I see you are asking about the Oracle e-Business Suite data model.
trying to fetch items ... and whose creation date is withing the last three years.
That is not what your query is doing. You are getting details of items made (via a WIP discrete job) within the last 3 years -- and you are getting a duplicate of the item for every time it was made (i.e., every occurrence in WIP_DISCRETE_JOBS_V).
If you want items made in the last 3 years, but you only want each item once, you should use an EXISTS (semi-join) to filter the rows instead of actually joining to WIP_DISCRETE_JOBS_V, which will cause duplicates). Something more along these lines:
SELECT *
FROM bom_bill_of_materials bom,
bom_inventory_components bic,
bom_components_b bcb,
bom_operational_routings_v borv,
bom_operation_sequences_v bosv,
bom_structures_b bsb,
bom_structure_types_b bst,
mtl_system_items_b msi,
mtl_system_items_tl msit,
org_organization_definitions ood --,
--wip_discrete_jobs_v wdjv
WHERE bom.bill_sequence_id = bic.bill_sequence_id
AND bic.component_sequence_id = bcb.component_sequence_id
AND bcb.bill_sequence_id = bsb.bill_sequence_id
AND bom.structure_type_id = bst.structure_type_id
AND bom.assembly_item_id = msi.inventory_item_id
AND bom.organization_id = msi.organization_id
AND bosv.routing_sequence_id = borv.routing_sequence_id
AND borv.assembly_item_id = bom.assembly_item_id
AND borv.organization_id = bom.organization_id
AND msi.inventory_item_id = msit.inventory_item_id
AND msi.organization_id = msit.organization_id
AND msit.organization_id = ood.organization_id
AND msit.language = USERENV ('LANG')
AND SYSDATE BETWEEN bcb.effectivity_date AND NVL (bcb.disable_date, SYSDATE)
AND msi.bom_enabled_flag = 'Y'
AND NVL (msi.enabled_flag, 'X') = 'Y'
AND ood.organization_id IN (203, 204, 328)
--AND borv.common_routing_sequence_id = wdjv.common_routing_sequence_id
--AND borv.assembly_item_id = wdjv.primary_item_id
--AND wdjv.creation_date > ADD_MONTHS (SYSDATE, -12 * 3)
--AND wdjv.wip_entity_name = '28799'
AND EXISTS ( SELECT 'discrete job within the last 3 years'
FROM wip_discrete_jobs_v wdjv
WHERE wdjv.common_routing_sequence_id = borv.common_routing_sequence_id
AND wdjv.primary_item_id = borv.assembly_item_id
AND wdjv.creation_date >= ADD_MONTHS(SYSDATE, -12*3)
)
--and MSI.SEGMENT1='9064090'
Note -- I kept this as close to your original query as possible and I didn't verify all the join conditions you used. So there may be some other bugs in your initial query that I have inadvertently duplicated.
One other thing, it's not a good practice to use the forms views, like WIP_DISCRETE_JOBS_V or BOM_OPERATIONAL_ROUTINGS_V. These views are to provide data to online forms. Not only can your performance suffer (because they contain joins that you may not need), but, if you go to Oracle's eTRM site (http://etrm.oracle.com/pls/etrm/etrm_pnav.show_object?c_name=BOM_OPERATIONAL_ROUTINGS_V&c_owner=APPS&c_type=VIEW), you will see this warning:
Warning: Oracle does not recommend you query or alter datausing this
view. It may change dramatically in subsequent minor or major
releases.
It is better to SELECT from the base tables.

How can I replicate a query to pull data side by side?

I have the following query, and what I am trying to do is take the query data, replicate it but change the names on the column headers from FY14 Q1 to FY14 Q2 and change the filters in the query.
Is there a way I can have this data shown all in one big table by combining the different queries??? Please help.
Select H.OpportunityID, H.CREATEDDATE, H.STAGENAME as 'Q1-14 Stage', H.CLOSEDATE as 'Q1-14 Close Date'
From
(SELECT
OpportunityID, Max(CREATEDDATE) as MaxDate
FROM [BVSFWarehouse].[dbo].[sf_OPPORTUNITYHISTORY]
WHERE
CREATEDDATE <= '2013-05-01'
GROUP BY
OpportunityID) X
Join [BVSFWarehouse].[dbo].[sf_OPPORTUNITYHISTORY] H ON H.OpportunityID = X.OpportunityID
And X.MaxDate = H.CREATEDDATE

SQL, Search by Date and not exists

I have two tables and need to search for all entries that exist in one table in another table by idProduct, only if the date (dateStamp) is less than or older than 7 days.
Because the api I'm using is restricted to only processing 3000 results at a time, the application will close and the next time I run the application I only want the idProducts that are say 3000 or greater for that idProduct, this will be run numerous times for the Suppliercode wll most likely already exist in the table.
So I've been looking at the not exists and getdate functions in sql but not been able to get the desired results.
SELECT
*
FROM
products
WHERE
(active = - 1)
AND suppliercode = 'TIT'
and (NOT EXISTS
(SELECT
idProduct
FROM compare
WHERE
(products.idProduct = idProduct)
OR (compare.dateStamp < DATEADD(DAY,-7,GETDATE()))))
Any pointers would be great, I've changed the OR to AND but it doesn't seem to bring back the correct results.
I am guessing you want to match the rows in the two tables by idProduct as right now your inner query (NOT EXISTS (SELECT idProduct FROM compare WHERE (products.idProduct = idProduct) OR (compare.dateStamp < DATEADD(DAY,-7,GETDATE())))) looks like it is finding all rows that don't match. As your subquery finds all rows that match or where the date is older than 7 days and makes sure that they don't exist.
Is this what your want?
SELECT *
FROM products as p
LEFT JOIN compare as c
ON p.idProduct = c.idProduct
WHERE p.active = -1 and p.suppliercode = 'TIT' and c.dateStamp < DATEADD(DAY,-7,GETDATE())
Have you tried this one yet?
SELECT * FROM products
WHERE (active = - 1) AND
suppliercode = 'TIT'
and ipProduct NOT IN
(
SELECT idProduct FROM compare
WHERE
(products.idProduct = idProduct) OR
(compare.dateStamp < DATEADD(DAY,-7,GETDATE()))
)
Try NOT IN instead:
...
and ProductId NOT IN
(SELECT
idProduct
FROM compare
WHERE
(products.idProduct = idProduct)
OR (compare.dateStamp < DATEADD(DAY,-7,GETDATE()))))
....