How to write update query using Inner join - sql-server

I have this query
Update ProductionDetails P Inner join
( SELECT Distinct A.BaseCode, A.BaseScale, (A.BaseScale * B.BasePer / 100) AS BaseVal, A.TreadCode, A.TreadScale, (A.TreadScale * B.TreadPer / 100) as TreadVal, A.InterfaceCode, A.LipCode, A.LipScale,
(A.LipScale * B.HsPer / 100) as LipVal, A.CenterCode, A.CenterScale, (A.CenterScale * B.CenterPer / 100) AS CenterVal, A.StencilNo
from productionDetails A inner join
BlendMaster B on (A.InterfaceCode = b.Category AND A.BaseCode = B.Base AND A.TreadCode = B.Tread AND A.centerCode = B.center)
Where B.Status = yes
) AS ResTable on ( P.StencilNo = ResTable.StencilNo )
Set P.BaseValue = ResTable.BaseVal, P.TreadValue = ResTable.TreadVal , P.LipValue = ResTable.LipVal, P.CenterValue = ResTable.CenterVal
I need to update ProductionDetails table on BaseValue, TreadValue, CenterValue, LipValue Fields with the calculated value in (SELECT Query ... ) AS ResTable .
if i write command to select from ResTable i get value, but if i update it says error "Operation must use an updateable query". i need to run this on MS Access 2013
Here is the query for sample data
CREATE TABLE ProductionDetails(StencilNo Text, LipCode Text, LipScale Text,LipValue Number,BaseCode Text,BaseScale Number,BaseValue Number,InterfaceCode Text,CenterCode Text,CenterScale Number,CenterValue Number,TreadCode Text,TreadScale Number,TreadValue Number)
Create Table BlendMaster (Category Text, Base Text, BasePer number , HsPer number, Center text, CenterPer number, Tread text, TreadPer number)
Insert into ProductionDetails (StencilNo, LipCode , LipScale ,BaseCode ,BaseScale , InterfaceCode ,CenterCode , CenterScale , TreadCode ,TreadScale )
VALUES ('C160405234', '-', 0,'BFA10',48.44,'BF10+CEG28' , 'CEG28', 36.5, 'TRR51', 52.56)
Insert into BlendMaster (Category, Base, BasePer ,HsPer, Center , CenterPer , Tread,TreadPer )
VALUES ('BF10+CEG28', 'BFA10',25, 25, 'CEG28', 15, 'TRR51', 18)

i think update should be done like this
UPDATE p
SET P.basevalue = ResTable.baseval,
P.treadvalue = ResTable.treadval,
P.lipvalue = ResTable.lipval,
P.centervalue = ResTable.centerval
from
#productiondetails P
INNER JOIN (SELECT A.basecode,
A.basescale,
( A.basescale * B.baseper / 100 ) AS
BaseVal,
A.treadcode,
A.treadscale,
( A.treadscale * B.treadper / 100 ) AS
TreadVal,
A.interfacecode,
A.lipcode,
A.lipscale,
( A.lipscale * B.hsper / 100 ) AS
LipVal,
A.centercode,
A.centerscale,
( A.centerscale * B.centerper / 100 ) AS
CenterVal,
A.stencilno
FROM #productiondetails A
INNER JOIN #blendmaster B
ON A.interfacecode = b.category
AND A.basecode = B.base
AND A.centercode = B.center )
---WHERE B.status = 'yes' this condtiton is not present in yout 2 tables)
ResTable
ON P.stencilno = ResTable.stencilno

Related

SQL Query running slow on the DB server

Execution plan is attached
SELECT a.*, k.UserPrivileges, k.Type
FROM NotifyInterests2 a, KUAF k
WHERE a.UserID = k.ID
AND EXISTS (SELECT ID FROM KUAF WHERE a.UserID = ID AND NOT Type IN (1, 2, 4))
AND (a.NodeID IN ( SELECT 0 UNION ALL ( SELECT DISTINCT( -1 * ID )
FROM KUAF WHERE Type = 5 ) UNION ALL ( SELECT DISTINCT AncestorID
FROM DTreeAncestors
WHERE Exists ( SELECT EventInt2 FROM LLEventQueue
WHERE EventHandlerID = 9001 AND EventSeqNo <=45075882 AND EventInt2 = DataID
UNION ALL SELECT EventInt2 * -1 FROM LLEventQueue
WHERE EventHandlerID = 9001
AND EventSeqNo <=45075882 AND EventInt2 = DataID ))))
that's quite the query =) Tip: try to 'group' the parts of your code for readability; it will make your life a 100 times easier; now while you're writing this and even more in the future when you're maintaining this =)
Some questions remain:
What do you call 'slow'?
How many records are present in each table?
How many records are returned by the query?
What are the indexes on the tables? (sp_helpindex)
Also, it probably would have been helpful to see the entire query plan, but one thing that stands out immediately is that KEAF doesn't seem to have clustered index. I presume it's thus also missing a Primary Key? As you have a field ID there I'd expect that this uniquely identifies each record? If so, add a PK to the table and check what effect this has on the entire query.
I've tried to re-arrange things a bit for readability and I ended up with below. I've gambled on some of the aliases as they are missing in the original query.
SELECT a.*, k.UserPrivileges, k.Type
FROM NotifyInterests2 a
JOIN KUAF k
ON k.ID = a.UserID
WHERE EXISTS ( SELECT kx.ID
FROM KUAF kx
WHERE kx.ID = a.UserID
AND NOT kx.Type IN (1, 2, 4) )
AND a.NodeID IN ( SELECT 0
UNION ALL
SELECT DISTINCT( -1 * k5.ID )
FROM KUAF k5
WHERE k5.Type = 5
UNION ALL
SELECT DISTINCT da.AncestorID
FROM DTreeAncestors da
WHERE EXISTS ( SELECT l1.EventInt2
FROM LLEventQueue l1
WHERE l1.EventHandlerID = 9001
AND l1.EventSeqNo <= 45075882
AND l1.EventInt2 = da.DataID
UNION ALL
SELECT l2.EventInt2 * -1
FROM LLEventQueue l2
WHERE l2.EventHandlerID = 9001
AND l2.EventSeqNo <= 45075882
AND l2.EventInt2 = da.DataID )
)
Some parts can be simplified I think.
This doesn't really make sense:
SELECT DISTINCT da.AncestorID
FROM DTreeAncestors da
WHERE EXISTS ( SELECT l1.EventInt2
FROM LLEventQueue l1
WHERE l1.EventHandlerID = 9001
AND l1.EventSeqNo <= 45075882
AND l1.EventInt2 = da.DataID
UNION ALL
SELECT l2.EventInt2 * -1
FROM LLEventQueue l2
WHERE l2.EventHandlerID = 9001
AND l2.EventSeqNo <= 45075882
AND l2.EventInt2 = da.DataID )
You're simply doing the same query twice in the WHERE EXISTS() part.
Also, as this part belongs to a WHERE IN (...) construction there's no real need for the DISTINCT. In fact, it's probably easier to convert it to a WHERE EXISTS() construction. Something like this:
AND ( a.NodeID = 0
OR EXISTS (SELECT *
FROM KUAF k5
WHERE k5.Type = 5
AND ( -1 * k5.ID ) = a.node_id)
OR EXISTS ( SELECT *
FROM DTreeAncestors da
WHERE da.AncestorID = a.NodeID
AND EXISTS ( SELECT *
FROM LLEventQueue l1
WHERE l1.EventHandlerID = 9001
AND l1.EventSeqNo <= 45075882
AND l1.EventInt2 = da.DataID )
)
Normally I'm no fan of OR but I think that in this case it might work.
So I end up with:
SELECT a.*, k.UserPrivileges, k.Type
FROM NotifyInterests2 a
JOIN KUAF k
ON k.ID = a.UserID
WHERE EXISTS ( SELECT kx.ID
FROM KUAF kx
WHERE a.UserID = kx.ID
AND NOT kx.Type IN (1, 2, 4) )
AND ( a.NodeID = 0
OR EXISTS (SELECT *
FROM KUAF k5
WHERE k5.Type = 5
AND ( -1 * k5.ID ) = a.node_id)
OR EXISTS ( SELECT *
FROM DTreeAncestors da
WHERE da.AncestorID = a.NodeID
AND EXISTS ( SELECT *
FROM LLEventQueue l
WHERE l.EventHandlerID = 9001
AND l.EventSeqNo <= 45075882
AND l.EventInt2 = da.DataID )
)
)
Give this a try and check the query plan. If it still is too slow we'll need to look at the indexes that are on the bespoken tables to see where we can optimize those.
You didn't mention if and which indexes exist in the table.
I would try creating the following indexes and see if there is any performance gain:
CREATE INDEX kuaf_idx_id_type ON KUAF (ID,Type);
CREATE INDEX kuaf_idx_type ON KUAF (Type);
CREATE INDEX lleventqueue_idx_eventha_eventin_dataid_eventse ON LLEventQueue (EventHandlerID,EventInt2,DataID,EventSeqNo);

Select top 1 subquery with parameters (SQL)

I am removing a user function which finds shows item prices based on configurations but the function is too slow.
Therefore I'm trying to write a query to do the same. This query finds the latest price that matches the required criteria
This is kind of what I'm going for but I cannot figure out how to handle this requirement correctly:
(Intellisesnse says s.inventdimid does not exist in the h subquery)
SELECT s.salesid
,s.itemid
,h.price
FROM salesline s
LEFT OUTER JOIN (
SELECT TOP 1 p.price
,p.itemid
,p.dataareaid
,l.inventdimid
FROM inventitemprice p
JOIN inventdim d ON d.dataareaid = p.dataareaid
AND d.inventdimid = p.inventdimid
JOIN inventdim l ON l.dataareaid = p.dataareaid
AND (
l.configid = d.configid
OR d.configid = ''
)
AND (
l.inventcolorid = d.inventcolorid
OR d.inventcolorid = ''
)
AND (
l.inventsizeid = d.inventsizeid
OR d.inventsizeid = ''
)
AND (
l.inventstyleid = d.inventstyleid
OR d.inventstyleid = ''
)
AND (p.ACTIVATIONDATE < getdate())
AND l.inventsiteid = d.inventsiteid
WHERE pricetype = 0
AND l.inventdimid = s.inventdimid /* <========= */
AND p.dataareaid = 'lkc'
ORDER BY activationdate DESC
,d.configid DESC
,d.inventcolorid DESC
,d.INVENTSIZEID DESC
,d.inventstyleid DESC
) AS h ON h.itemid = s.itemid
AND h.DATAAREAID = s.DATAAREAID
AND h.INVENTDIMID = s.inventdimid
WHERE s.dataareaid = 'lkc'
AND s.SALESSTATUS = 1
What would be the appropriate method for querying this?

How will SQL Server execute this WITH clause

I have the following query. Here 'B' is giving me non repeated MessageIds and i am using them in subquery with A, B is internally using A.
So when i call SELECT in the last part, will it execute A again or will it use data already fetched while B was being called ?
WITH A as (
SELECT z.Name, ze.Inside, ze.MessageId, ze.DateTime
FROM ZoneStateEntries ze
INNER JOIN Zone z
ON ze.ZoneId = z.ZoneId
WHERE ze.ObjectId = 1324
AND (Inside = 1 OR Inside = 0)
AND ze.DateTime BETWEEN '2018-10-22 00:00:00' AND '2019-11-05 00:00:00'
),
B as (
SELECT a.MessageId
FROM A a
INNER JOIN A b
on a.MessageId = b.MessageId
GROUP BY a.MessageId
HAVING COUNT(a.MessageId) = 1
)
SELECT *
FROM A
WHERE MessageId IN (
SELECT *
FROM B
)
AND a.Inside = 1
ORDER BY DateTime DESC
The data here is huge and we can't afford to execute query A multiple times. Can we optimize it further?
A a INNER JOIN A b looks like unnecessary. You can use COUNT(DISTINCT MessageId) for getting unique messages.
WITH A as (
SELECT z.Name, ze.Inside, ze.MessageId, ze.DateTime
FROM ZoneStateEntries ze
INNER JOIN Zone z
ON ze.ZoneId = z.ZoneId
WHERE ze.ObjectId = 1324
AND (Inside = 1 OR Inside = 0)
AND ze.DateTime BETWEEN '2018-10-22 00:00:00' AND '2019-11-05 00:00:00'
)
SELECT *
FROM A
WHERE MessageId IN (
SELECT MessageId
FROM A
GROUP BY MessageId
HAVING COUNT(DISTINCT MessageId) = 1
)
AND a.Inside = 1
ORDER BY DateTime DESC

How to SUM a column value in MSSQL

I am new to mssql ,Here I need to SUM a column values.
But in my case have some joins between the tables finally I have a column with 2 rows of output .
What I want to do is I want to SUM the final output of my query.
This is my query :
SELECT
SUM(ESCD.ITEM_QTY) * ((SELECT COLOC_PROD_PRICE
FROM LOM_LNK_PROD_COMP
WHERE COLOC_PROD_CODE = ITEM_ID)
/
((SELECT LMUL.UOL_CONV_QTY
FROM LOM_MST_UOM_LINK AS LMUL
JOIN LOM_MST_PRODUCT AS LMP
ON LMUL.UOL_MAIN_UOM_CODE = LMP.PROD_STOCK_UOM
AND LMP.PROD_CODE = ESCD.ITEM_ID)/LMUL.UOL_CONV_QTY )) AS 'TOTAL_AMOUNT'
FROM EC_SHOPPING_CART_DETAIL AS ESCD
JOIN LOM_MST_UOM_LINK AS LMUL
ON LMUL.UOL_MAIN_UOM_CODE = ITEM_PACK_SIZE
WHERE CREATED_BY = 'xyz'
AND CHECK_OUT = 'FALSE'
GROUP BY ITEM_ID,LMUL.UOL_CONV_QTY
Output :
Expected AS :
can anyone help me to solve this .
Try the following:
SELECT
SUM(X.TOTAL_AMOUNT) AS 'TOTAL_AMOUNT'
FROM
(
SELECT
SUM(ESCD.ITEM_QTY) * ((SELECT COLOC_PROD_PRICE
FROM LOM_LNK_PROD_COMP
WHERE COLOC_PROD_CODE = ITEM_ID)
/
((SELECT LMUL.UOL_CONV_QTY
FROM LOM_MST_UOM_LINK AS LMUL
JOIN LOM_MST_PRODUCT AS LMP
ON LMUL.UOL_MAIN_UOM_CODE = LMP.PROD_STOCK_UOM
AND LMP.PROD_CODE = ESCD.ITEM_ID)/LMUL.UOL_CONV_QTY )) AS 'TOTAL_AMOUNT'
FROM EC_SHOPPING_CART_DETAIL AS ESCD
JOIN LOM_MST_UOM_LINK AS LMUL
ON LMUL.UOL_MAIN_UOM_CODE = ITEM_PACK_SIZE
WHERE CREATED_BY = 'xyz'
AND CHECK_OUT = 'FALSE'
GROUP BY ITEM_ID,LMUL.UOL_CONV_QTY
) X;

how to convert the below subquery into joins using one update statement

Below is a complete query I have and the ultimate aim is to update the claim table. But it should be only one statement without any subquery, only joins are allowed because I am going to run this in an appliance which won't support subquery:
DECLARE #DecWdrwn as TABLE(CtryId smallint, CmId int, DecWdrwnDt int);
WITH s AS
(
SELECT
Ctryid,CmId,Dt,
ISNULL((
SELECT max(CmHistDtTmId)
FROM ClaimHistory l
WHERE St = 3
AND l.Ctryid = c.Ctryid
AND l.CmId = c.CmId)
, 0) MaxDec,
ISNULL((
SELECT max(CmHistDtTmId)
FROM ClaimHistory l
WHERE St = 7
AND l.Ctryid = c.Ctryid
AND l.CmId = c.CmId)
, 0) MaxSet
FROM
ClaimHistory c
WHERE
St =3
)
INSERT INTO #DecWdrwn
SELECT CtryId, CmId, Max(Dt) DecDt
FROM s
WHERE MaxSet > MaxDec
GROUP BY CtryId,CmId
Your response is much appreciated...
UPDATE Claims
SET CmDclnWdwnDt = (
SELECT DecWdrwnDt
FROM #DecWdrwn d
WHERE d.CmId = Claims.CmId
AND d.CtryId = Claims.CtryId
)
WHERE EXISTS (
SELECT *
FROM #DecWdrwn d
WHERE d.CmId = Claims.CmId
AND d.CtryId = Claims.CtryId
)
Please try INNER JOIN Update:
UPDATE a
SET a.CmDclnWdwnDt = b.DecWdrwnDt
FROM Claims a, #DecWdrwn b
WHERE a.CmId = b.CmId AND
a.CtryId =b.CtryId

Resources