I've inherited data from another provider and have 2 tables to clean up
Rooms
Items
Items are within a Room and are linked via Rooms.RoomID / Items.RoomID
Each time an Item has been inspected it has created a Duplicate of the Room & Item, so I have 6 records for each Room and each Item (Each with a unique RoomID, so 1 to 1)
My aim is to remove the Duplicate Rooms and keep only the latest set of records, then update the Items table with the RoomID (So I have 1 to Many i.e. 1 Room with 6 Item records)
I can GROUP the Rooms and obtain the MAX RoomID but don't know how to do the UPDATE
A kind of suedo would be this:
UPDATE a
SET a.RoomID = MAX(b.RoomID)
FROM [dbo].[tmp_Items] a
inner join [dbo].[tmp_Rooms] b on b.PropertyID = a.PropertyID
and b.FloorLevel = a.FloorLevel
and b.Reference = a.Reference
The combination of PropertyID, FloorLevel, and Reference provides a unique link between Items and Rooms as these columns are in both tables and Reference is unique to each floor of a property (Each Room of each Floor is numbered starting from 1)
Any help or guidance appreciated :)
Use a subquery to aggregate before joining:
UPDATE i
SET i.RoomID = r.max_roomid
FROM [dbo].[tmp_Items] i JOIN
(SELECT PropertyID, FloorLevel, Reference, MAX(r.RoomID) as max_roomid
FROM [dbo].[tmp_Rooms] r
GROUP BY PropertyID, FloorLevel, Reference
) r
ON r.PropertyID = i.PropertyID AND
r.FloorLevel = i.FloorLevel AND
r.Reference = i.Reference;
Related
I am writing a query which will be used to populate a report used for putting away stock in a warehouse.
The report has 3 parameters, a source stock location, source bin number and a destination stock location.
The stock will be currently held in source stock location and bin number.
The destination stock location is where the stock needs to be moved to.
Each Variant has a default bin number in each stock location.
Multiple variants can have the same default bin number.
Bin numbers may not be alphabetical around the warehouse, and so each bin number is assigned a walk route, as the most efficient walking route around the warehouse.
The report will look at the default bin number associated with the item in the destination stock location, and if empty, offer that as the put away suggestion.
If the default bin number is not empty, it will look for the next available empty bin in the destination stock location (where walk route is higher than default bin), and then offer that as the put away suggestion.
The query works fine, and does exactly that, however it is reporting the same bin as previous "NextBinNo" suggestions in rows above.
How can I get the OUTER APPLY NextBinNo to filter out any previously suggested bins in higher rows of data? Also if two items have the same default bin number, it should use the NextBinNo for the second row with this default bin no.
My current query:
Select
row_number() Over(Order by DestSL.sl_id) as RowNo,
Stock_location.sl_name,
bin_number.bn_bin_number,
variant_detail.vad_variant_code,
variant_detail.vad_description,
variant_transaction_header.vth_current_quantity,
variant_transaction_header.vth_batch_number,
purchase_order_header.poh_order_number,
supplier_detail.sd_ow_account,
DestSL.sl_id as 'DestinationSLID',
DestSL.sl_name as 'DestinationStockLocation',
DestDefaultBin.bn_bin_number as 'DestinationDefaultBin',
DestDefaultBin.bn_walk_route as 'DestinationDefaultWalkRoute',
isnull(DestDefaultBinQty.BinQty,0) as QtyInDefaultBin,
NextBinNo.NextBinNo as 'NextBinNo',
NextBinNo.NextWalkRoute as 'NextBinWalkRoute',
isnull(NextBinNo.BinQty,0) as 'NextBinQty',
case when DestDefaultBin.bn_bin_number is null
then 'Not Stocked in This Location'
Else
case when isnull(DestDefaultBinQty.BinQty,0) > 0
then
case when NextBinNo.NextBinNo is NULL
then 'No Free Bin'
Else NextBinNo.NextBinNo
End
Else DestDefaultBin.bn_bin_number
End
End as 'Put Away Destination'
From variant_transaction_header
join bin_number on bin_number.bn_id = variant_transaction_header.vth_bn_id
join stock_location on stock_location.sl_id = variant_transaction_header.vth_sl_id
join variant_detail on variant_detail.vad_id = variant_transaction_header.vth_vad_id
join transaction_type on transaction_Type.tt_id = variant_transaction_header.vth_tt_id
left join purchase_order_line on purchase_order_line.pol_id = variant_transaction_header.vth_pol_id
left join purchase_order_header on purchase_order_header.poh_id = purchase_order_line.pol_poh_id
left join supplier_detail on supplier_detail.sd_id = purchase_order_header.poh_sd_id
join stock_location DestSL on DestSL.sl_id = #DestinationStockLoc
left join variant_stock_location DestVSL on DestVSL.vsl_vad_id = variant_detail.vad_id and DestVSL.vsl_sl_id = DestSL.sl_id
left join bin_number DestDefaultBin on DestDefaultBin.bn_id = DestVSL.vsl_bn_id
left join
(select sum(variant_transaction_header.vth_current_quantity) as BinQty,
variant_transaction_header.vth_bn_id
from variant_transaction_header
join transaction_type on transaction_Type.tt_id = variant_transaction_header.vth_tt_id
Where variant_transaction_header.vth_current_quantity > 0
and transaction_type.tt_transaction_type = 'IN' and transaction_Type.tt_update_current_qty = 1
Group by variant_transaction_header.vth_bn_id) as DestDefaultBinQty on DestDefaultBinQty.vth_bn_id = DestDefaultBin.bn_id
Outer Apply
(select top 1
row_number() Over(Order by NextBin.bn_bin_number) as RowNo,
NextBin.bn_bin_number as NextBinNo,
NextBin.bn_walk_route as NextWalkRoute,
BinQty.BinQty
from
Stock_location DestSL
Join bin_number NextBin on NextBin.bn_sl_id = DestSL.sl_id
left join
(select sum(variant_transaction_header.vth_current_quantity) as BinQty,
variant_transaction_header.vth_bn_id
from variant_transaction_header
join transaction_type on transaction_Type.tt_id = variant_transaction_header.vth_tt_id
Where variant_transaction_header.vth_current_quantity > 0
and transaction_type.tt_transaction_type = 'IN' and transaction_Type.tt_update_current_qty = 1
Group by variant_transaction_header.vth_bn_id) as BinQty on BinQty.vth_bn_id = NextBin.bn_id
Where NextBin.bn_sl_id = #DestinationStockLoc
and NextBin.bn_walk_route > DestDefaultBin.bn_walk_route
And isnull(BinQty.BinQty,0) = 0
order by NextBin.bn_walk_route, nextbin.bn_bin_number) as NextBinNo
where variant_transaction_header.vth_current_quantity > 0
and transaction_type.tt_transaction_type = 'IN' and transaction_Type.tt_update_current_qty = 1
and stock_location.sl_id = #SourceStockLoc and bin_number.bn_id = #SourceBinNo
You can see my current results below:
Row2 is using the NextBinNo as the default bin has stock.
Row3 is also suggesting using AA08A2 as the next bin.
Row 6 is currently suggesting AA01A2 but that has already been suggested in Row1.
Just to answer this, in the end I could not achieve what I wanted directly in SQL.
The data is ultimately being returned to a report writer which can run Visual Basic code.
I had to execute the NextBinNo sub query separately in VB.
In VB I can define a string which contains a list of all the "used" bin numbers and so on each row this is referenced in the WHERE of the query to check it has not been used in a row above.
I could then return this value as a new column dynamically inserted in the dataset at run time.
I have the below tables in my DB.
Orders:
OrderNo.........ItemNo........OrderQty
1000________10_________10
2000________20_________10
VendorPO:
OrderNo.........ItemNo........VendorPO........POQty
1000________10_________100__________5
2000________20_________100__________7
2000________20_________200__________3
And I used this Query:
SELECT Order.OrderNo, Order.ItemNo, Order.OrderQty, VendorPO.VendorPO, VendorPO.POQty
FROM [Order]
INNER JOIN VendorPO ON (Order.ItemNo = VendorPO.ItemNo)
AND (Order.OrderNo = VendorPO.OrderNo);
With these results:
Query Result
OrderNo.........ItemNo........OrderQty........VendorPO........POQty
1000________10__________10_________100__________5
2000________20__________10_________100__________7
2000________20__________10_________200__________3
I want to avoid repetition of the quantity in the query result, where Item quantity 10 is repeated twice against two PO reference with POQty 3 and 7.
I appreciate your support on finding a way to avoid order quantity repetition.
I have tried to find answers to this question on the net but am not really getting anywhere.
I tried to do screen shots but don't have enough rep. Anyway.
Here is my current query structure.
Tables:
tblInventoryItems(intSerial, intItem, intStyle) -This is the list of current items that are on inventory(built or unbuilt)
tblLocations(intLocationID, chrLocationName, intLotType)
tblItemStyles(intItemStyleID, intBasic Style)
tblItemList(intItemID, intType, intSubtype, intStyle)
tblCommissions(intBuildEvent, intItemType, intItemSubtype)
tblBuildEvents(intSerial, intBuildEventType, dtEventDate)
First Set of Queries
qryCompletedBarns:
SELECT dbo.tblInventoryItems.intSerial,dbo.tblBuildEvents.dtEventDate
FROM dbo.tblItemList
INNER JOIN dbo.tblItemStyles ON
dbo.tblItemList.intStyle = dbo.tblItemStyles.intBasicStyle
INNER JOIN dbo.tblInventoryItems ON
dbo.tblItemList.intItemID = dbo.tblInventoryItems.intItem AND
dbo.tblItemStyles.intItemStyleID = dbo.tblInventoryItems.intStyle
INNER JOIN dbo.tblCommissions ON
dbo.tblItemList.intSubType = dbo.tblCommissions.intItemSubtype
AND dbo.tblItemList.intType = dbo.tblCommissions.intItemType
INNER JOIN dbo.tblBuildEvents ON
dbo.tblBuildEvents.intBuildEventType = dbo.tblCommissions.intBuildEvent AND
dbo.tblInventoryItems.intSerial = dbo.tblBuildEvents.intSerial
WHERE (dbo.tblCommissions.ynCompletesBarn = 1)
So First we select all items that have a build event that qualifies them as completed. An item can have multiple build events but there is only one that qualifies it as completed
qryCompletedBarnDateFilter:
SELECT qryCompletedBarns.intSerial, qryCompletedBarns.dtEventDate
FROM qryCompletedBarns
WHERE (((qryCompletedBarns.dtEventDate)<=InventoryDate()));
Then we jump to Access and filter those results by a UDF that pulls the criteria for the build date of the item(Saved report definitions are stored in a table).
Now, we have a list of all Inventory items that meet the first criteria, which is that they must be built on or before the Inventory Date that the user selects.
Second set of queries:
qryInventoryLogDateFilter:
SELECT tblHaulLogs.*, tblHaulLogs.dtmHaulDate
FROM tblHaulLogs
WHERE (((tblHaulLogs.dtmHaulDate)<=InventoryDate()));
Get all the Haullogs (or you could call them inventory transactions) that are equal to or older than the InventoryDate criteria.
qryLastLogForBarn:
SELECT t1.intSerial, t1.intHaulType, t1.intDestinationSource, t1.intDestination
FROM qryInventoryLogDateFilter AS t1
LEFT JOIN qryInventoryLogDateFilter AS t2
ON (t1.intLogID < t2.intLogID) AND (t1.intSerial = t2.intSerial)
WHERE t2.intLogID IS NULL;
Get the last inventory transaction for each Inventory Item. This query is actually very fast when executed on the server natively.
qryInventoryCurrentCustomer:
SELECT tblSales.intSerial, tblCustomers.chrFirstName + ' ' + tblCustomers.chrLastName
AS chrCustomerName, tblSales.dtSaleDate
FROM tblSales INNER JOIN tblCustomers ON
tblSales.intCustomer = tblCustomers.intCustID
LEFT OUTER JOIN tblHaulLogs ON
tblSales.intSaleID = tblHaulLogs.intOrigon
WHERE (tblHaulLogs.intHaulType IS NULL) AND (tblSales.bolSaleCancelled = 0)
OR (tblHaulLogs.intHaulType <> 3) AND
(tblSales.intOrderType <4) AND (tblSales.bolSaleCancelled = 0)
GROUP BY tblSales.intSerial, tblCustomers.chrFirstName + ' ' + tblCustomers.chrLastName,
tblSales.dtSaleDate, tblSales.intOrderType;
This query does not actually return an "Inventory Item" but rather checks the sales table and returns a customer name if the inventory item was sold.
Now we finally join the two "sections" and the "Current Customer Query":
SELECT qryCompletedBarnDateFilter.intSerial, qryLastLogForBarn.intHaulType,
IIf(IsNull([intDestination]),7,[intDestination]) AS Location,
qryInventoryCurrentCustomer.chrCustomerName,
qryInventoryCurrentCustomer.dtSaleDate, qryCompletedBarnDateFilter.dtEventDate
FROM (qryCompletedBarnDateFilter
LEFT JOIN qryLastLogForBarn
ON qryCompletedBarnDateFilter.intSerial = qryLastLogForBarn.intSerial)
LEFT JOIN qryInventoryCurrentCustomer
ON qryCompletedBarnDateFilter.intSerial = qryInventoryCurrentCustomer.intSerial
WHERE (((qryLastLogForBarn.intDestinationSource)=1
Or (qryLastLogForBarn.intDestinationSource) Is Null));
Then we join to the "Locations" table to get the name of the inventory item's location, and also filter out a certain type of location.
qryRetailBarnsOnInventory:
SELECT qryBarnsOnInventory.intSerial, qryBarnsOnInventory.Location,
tblLocations.chrLocationName, qryBarnsOnInventory.chrCustomerName,
qryBarnsOnInventory.dtEventDate, qryBarnsOnInventory.intHaulType
FROM tblLocations
INNER JOIN qryBarnsOnInventory
ON tblLocations.intLocationID = qryBarnsOnInventory.Location
WHERE (((tblLocations.intLotType)=1));
The Final Query:
SELECT tblItemStyles.chrItemStyle, tblInventoryItems.intSerial,
tblItemSizeList.intItemSize, tblItemPrices.ccyPrice,
tblInventoryItems.txtOptions, qryRetailBarnsOnInventory.chrCustomerName,
qryRetailBarnsOnInventory.dtEventDate, qryRetailBarnsOnInventory.intHaulType,
qryRetailBarnsOnInventory.chrLocationName, tblItemList.intType,
tblItemList.intSubType, tblItemList.intStyle, tblItemSizes.intItemSizeID,
tblItemStyles.intItemStyleID, tblItemPrices.intPriceSheet,
tblInventoryItems.bolinTransit
FROM tblItemSizeList INNER JOIN (tblItemSizes INNER JOIN
(qryRetailBarnsOnInventory INNER JOIN (((tblItemList INNER JOIN
tblItemPrices ON tblItemList.intItemID = tblItemPrices.intItemID)
INNER JOIN tblItemStyles ON tblItemList.intStyle = tblItemStyles.intBasicStyle)
INNER JOIN tblInventoryItems
ON (tblItemList.intItemID = tblInventoryItems.intItem)
AND (tblItemStyles.intItemStyleID = tblInventoryItems.intStyle))
ON qryRetailBarnsOnInventory.intSerial = tblInventoryItems.intSerial)
ON tblItemSizes.intItemSizeID = tblItemList.intSize)
ON tblItemSizeList.intItemSizeID = tblItemSizes.intSize
WHERE (((tblItemList.intType) Like ItemType())
AND ((tblItemList.intSubType) Like ItemSubType())
AND ((tblItemList.intStyle) Like BasicStyle())
AND ((tblItemSizes.intItemSizeID) Like ItemSize())
AND ((tblItemStyles.intItemStyleID) Like SubStyle())
AND ((tblItemPrices.intPriceSheet)=1)
AND ((tblInventoryItems.bolinTransit)=False)
AND ((IIf(IsNull([intHaulType]),2,3)) Like NewUsed())
AND ((IIf(IsNull([chrCustomerName]),2,3)) Like IsSold())
AND ((qryRetailBarnsOnInventory.Location) Like LotID()));
Summary:
In plain English, here is what I want to happen:
Get all Inventory Items from the inventory items table that were completed on or before the date criteria, then get the last inventory transaction on or before the date criteria for each of those items. And then filter by additional criteria that the user provides
I have the correct results but it is SLOW! Like 10-15 seconds. And we do a tremendous amount of queries every day.
What my idea was is to put this all on SQL Server in sprocs or views. If I do this all with views on SQL server and type manual criteria in, it's blazing fast. The problem I have is that every query requires a parameter. Not just the last one. I can pass parameters for the last query all right with a passthrough query but how do I pass the date criteria parameters for the first query?
EDIT:
Would it be possible to get the date criteria from another table? The criteria is stored in another table in the DB. If I could perform some kind of lookup to get that value and use it as the criteria that would make life really simple.
I have following view which is working but not sure how to add 2 tables to join.
This table is adres1 and it will join on the IDENT# and IDSFX# to table
prodta.adres1 called adent# and adsfx#, there I need a col. ads15.
then i also need to get the ship to, row in this adres1. this we get first from the order table, prodta. oeord1 in col. odgrc#. This grc# is 11 pos and is combined 8 and 3 of the ent and suf. these 2 represent the ship to record and looking in same table adres1 (we do have many logical views on them if it's easier, like adres15) we can get col. ADSTTC for the ship to state.
Not sure if can included these 2 new parts to the current view created code below. Please ask if something not clear, it's an old system and somewhat developed convoluted.
CREATE VIEW Prolib.SHPWEIGHTP AS SELECT
T01.IDORD#,
T01.IDDOCD,
T01.IDPRT#,
t01.idsfx#,
T01.IDSHP#,
T01.IDNTU$,
T01.IDENT#,
(T01.IDNTU$ * T01.IDSHP#) AS LINTOT,
T02.IAPTWT,
T02.IARCC3,
T02.IAPRLC,
T03.PHVIAC,
T03.PHORD#,
PHSFX#,
T01.IDORDT,
T01.IDHCD3
FROM PRODTA.OEINDLID T01
INNER JOIN PRODTA.ICPRTMIA T02 ON T01.IDPRT# = T02.IAPRT#
INNER JOIN
(SELECT DISTINCT
PHORD#,
PHSFX#,
PHVIAC,
PHWGHT
FROM proccdta.pshippf) AS T03 ON t01.idord# = T03.phord#
WHERE T01.IDHCD3 IN ('MDL','TRP')
I'm not exactly clear on what you're asking, and it looks like some of the column-names are missing from your description, but this should get you pretty close:
CREATE VIEW Prolib.SHPWEIGHTP AS
SELECT T01.IDORD#,
T01.IDDOCD,
T01.IDPRT#,
t01.idsfx#,
T01.IDSHP#,
T01.IDNTU$,
T01.IDENT#,
( T01.IDNTU$ * T01.IDSHP# ) AS LINTOT ,
T02.IAPTWT,
T02.IARCC3,
T02.IAPRLC,
T03.PHVIAC,
T03.PHORD#,PHSFX#,
T01.IDORDT,
T01.IDHCD3,
t04.ads15
FROM PRODTA.OEINDLID T01
INNER JOIN PRODTA.ICPRTMIA T02
ON T01.IDPRT# = T02.IAPRT#
INNER JOIN (SELECT DISTINCT
PHORD#,
PHSFX#,
PHVIAC,
PHWGHT
FROM proccdta.pshippf) AS T03
ON t01.idord# = T03.phord#
JOIN prodta.adres1 as t04
on t04.adent# = t01.adent#
and t04.adsfx# = t01.adsfx#
JOIN prodta.oeord1 t05
on t05.odgrc# = T01.IDENT# || T01.SUFFIX
WHERE T01.IDHCD3 IN ('MDL','TRP')
Let me know if you need more details.
HTH !
Please pardon me if this question has been asked before, but I simply don't have enough vocabulary to search for what I need as a novice in data bases.
I am using SQL server 2008.
I have a table tblPDCDetails with several columns. One of the columns PDCof holds values :
"A"(for applicant),
"C" for coapplicant,
"G" (for Guarantor).
Another column HolderID holds uniqueid (of holder).
The PDCHolders reside in their respective tables: Applicants in tblApplBasicDetails, CoApllicants in their own table and so on.
Now what I need is how should I retrive the names of holders from their respective tables, depending on the value in PDCof column.
Can I do it at all?
If no how should I work around this?
This should do:
SELECT A.*,
COALESCE(B.Name,C.Name,D.Name) Name
FROM dbo.tblPDCDetails A
LEFT JOIN dbo.tblApplBasicDetails B
ON A.HolderID = B.HolderID
AND A.PDCof = 'A'
LEFT JOIN dbo.tblCoApplBasicDetails C
ON A.HolderID = C.HolderID
AND A.PDCof = 'C'
LEFT JOIN dbo.tblGuarantorlBasicDetails D
ON A.HolderID = D.HolderID
AND A.PDCof = 'G'
The other option is to use a case switch:
Select case Main.PDCof
when 'A' then (select HolderID from Applicants where main.value = value)
when 'C' then (select HolderID from CoApplicants where main.value = value)
when 'G' then (select HolderID from Guarantor where main.value = value)
end
,main.*
from tblPDCDetails main
Depends on whether you run this a few times a day, or a few thousand times an hour