Issue with query in DB2 - sql-server

I was using below query in sql server to update the table "TABLE" using the same table "TABLE". In sql server the below query is working fine.But in DB2 its getting failed.Not sure whether I need to make any change in this query to work in DB2.
The error I am getting in DB2 is
ExampleExceptionFormatter: exception message was: DB2 SQL Error:
SQLCODE=-204, SQLSTATE=42704
This is my input Data and there you can see ENO 679 is repeating in both round 3 and round 4.
My expected output is given below. Here I am taking the ID and round value from round 4 and updating rownumber 3 with the ID value from rownumber 4.
My requirement is to find the ENO which is exist in both round 3 and round 4 and update the values accordingly.
UPDATE TGT
SET TGT.ROUND = SRC.ROUND,
TGT.ID = SRC.ID
FROM TABLE TGT INNER JOIN TABLE SRC
ON TGT.ROUND='3' and SRC.ROUND='4' and TGT.ENO = SRC.ENO
Could someone help here please. I tried something like this.But its not working
UPDATE TABLE
SET ID = (SELECT t.ID
FROM TABLE t, TABLE t2
WHERE t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3'
) ,
ROUND= (SELECT t.ROUND
FROM TABLE t, TABLE t2
WHERE t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3')
where ROUND='3'

You may try this. I think the issue is you are not relating your inner subquery with outer main table
UPDATE TABLE TB
SET TB.ID = (SELECT t.ID
FROM TABLE t, TABLE t2
WHERE TB.ENO=t.ENO ---- added this
and t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3'
) ,
TB.ROUND= (SELECT t.ROUND
FROM TABLE t, TABLE t2
WHERE TB.ENO=t.ENO --- added this
and t.ENO = t2.ENO AND t.ROUND= ='4' AND t2.ROUND='3')
where tb.ROUND='3'

Try this:
UPDATE MY_SAMPLE TGT
SET (ID, ROUND) = (SELECT ID, ROUND FROM MY_SAMPLE WHERE ENO = TGT.ENO AND ROUND = 4)
WHERE ROUND = 4 AND EXISTS (SELECT 1 FROM MY_SAMPLE WHERE ENO = TGT.ENO AND ROUND = 4);
The difference with yours is that the correlated subquery has to be a row-subselect, it has to guarantee zero or one row (and will assign nulls in case of returning zero rows). The EXISTS subquery excludes rows for which the correlated subquery will not return rows.

Related

Best way to attack a confusing SQL issue in inserting data into a TEMP table

I'm working in SQL Server 2016. Confusing problem with SQL issue. I have a TEMP table that contains unique rows. I have to insert 5 PRODUCTID values for each row each row based on another column value, AgentNo, in this temp table. The PRODUCTID value, there are 5 of them, comes from another table but there is no relationship between the tables. So my question is how do I insert a row for each ProductID into this temp table for each unique row that is currently in the temp table.
Here is a pic of the TEMP table that requires 5 rows for each:
Here is a pic of what I'm needing to come away with:
Here is my SQL code for both TEMP tables:
IF OBJECT_ID('tempdb..#tempTarget') IS NOT NULL DROP TABLE #tempTarget
SELECT 0 as ProductID, 1 as [Status], a.AgentNo, u.UserID, u.[Password], 'N' as AdminID, tel.LocationSysID --, tel.OwnerID, tel.LocationName, a.OwnerSysID, a.AgentName
INTO #tempTarget
FROM dbo.TEST_EvalLocations tel
INNER JOIN dbo.AGT_Agent a
ON tel.LocationName = a.AgentName
INNER JOIN dbo.IW_User u
ON a.AgentNo = u.UserID
WHERE tel.OwnerID = 13313
AND tel.LocationSysID <> 15434;
SELECT * FROM #tempTarget WHERE LocationSysID NOT IN (15425, 15434);
GO
-- Create source table
IF OBJECT_ID('tempdb..#tempSource') IS NOT NULL DROP TABLE #tempSource
SELECT DISTINCT lpr.ProductID
INTO #tempSource
FROM dbo.Eval_LocationProductRelationship lpr
WHERE lpr.ProductID IN (16, 15, 13, 14, 12) --BETWEEN 15435 AND 15595
Sorry I could not get this into a DDL file as these are TEMP tabless. Any help/direction would be appreciated. Thanks.
CROSS JOIN will be the best solution for your case.
If you only want 5 rows for each data in First table means, simply use the below cross join query.
SELECT B.ProductID,
A.[Status],
A.AgentNo,
A.UserID,
A.[Password] AS Value,
A.AdminID,
A.LocationSysID
FROM #tempTarget A
CROSS JOIN tempSource B
If you want additional row with 0, then you have to insert a 0 into your second temp table and use the same query.
INSERT INTO #tempSource SELECT 0
If i understand correctly following is the scenario,
One Temp table has all the content.
select * from #withoutProducts
product table
select * from #products
Then following is the query your are looking for
select a.ProductID,[Status],AgentNo,UserID,[value]
from #products a cross join #withoutProducts b
order by AgentNO,a.productID

Select from multiple tables without cartesian product

I'm trying to create a command to copy the details of client memberships from one database to another with identical structure. I've pared it down to the bare essentials for the purposes of the question so the four items to copy are the expiry date, the subscription ID, the client ID and the item ID (which is the service which comprises the subscription).
The clients have a common GUID in both bases. The subscription ID is a unique long int which should be the same in both bases and the expiry date is just a date. So far, so easy. The tricky part is that the item_id is not necessarily the same in each database. I need to map from one to the the other with a where statement, which I know how to do.
My problem is that I need to select from the destination database's own ITEM table (item_0) in order to get and insert the correct item_id and when I do this I get thousands of duplicate rows returned. I assume I need to use a join to avoid this but as I have nothing meaningful to join item_0 to I can't get any results.
insert into DestDB..subscription (expiry_date,id,client_id,item_id)
select
sub_1.expiry_date,
sub_1.id,
cli_0.id as client_id,
item_0.id as item_id,
from SourceDB..subscription sub_1,
DestDB..item item_0,
DestDB..client cli_0
inner join SourceDB..client cli_1
on cli_1.[guid] = cli_0.[guid]
where sub_1.id not in (select id from DestDB..subscription)
and item_0.id =
(select id from DestDB..collectiondetails
where service_ID =
(select id from DestDB..service s_0 where s_0.code =
(select code from SourceDB..service s_1 where s_1.id =
(select service_ID from Source..collectiondetails item_1 where item_1.id = sub_1.item_id)))
and collection_ID =
(select id from DestDB..collection col_0
where col_0.code =
(select code from SourceDB..collection col_1 where col_1.id =
(select collection_ID from SourceDB..collectiondetails item_1 where item_1.id = sub_1.collection_ID)))
)
I am afraid the updated question is even more confusing. Is this Select in Where clause guaranteed to return one record only or should it be in instead of =?
If there is no rule to identify a particular DestDB..item from the list of matching then the top one should do as well. It would still seem that item_0 can be omitted altogether:
insert into DestDB..subscription (expiry_date,id,client_id,item_id)
select
sub_1.expiry_date,
sub_1.id,
cli_0.id as client_id,
(select Top 1 id from DestDB..collectiondetails --<- Limit to top 1 only
where service_ID =
(select id from DestDB..service s_0 where s_0.code =
(select code from SourceDB..service s_1 where s_1.id =
(select service_ID from SourceDB..collectiondetails item_1 where item_1.id = sub_1.item_id)))
and collection_ID =
(select id from DestDB..collection col_0
where col_0.code =
(select code from SourceDB..collection col_1 where col_1.id =
(select collection_ID from SourceDB..collectiondetails item_1 where item_1.id = sub_1.collection_ID)))
) as item_id,
from SourceDB..subscription sub_1,
DestDB..client cli_0
inner join SourceDB..client cli_1
on cli_1.[guid] = cli_0.[guid]
where sub_1.id not in (select id from DestDB..subscription)
Please note: if DestDB..item is empty the question example statement would not insert anything, but this answer one - would with item_id set to NULL.
I personally would try splitting this task into two separate statements in one transaction:
Insert into target table with NULL item_id.
Update target table with new item_id where item_id is NULL.
(optional) Delete unwanted records where appropriate item_id could not be found.

How to compare records in same SQL Server table

My requirement is to compare each column of row with its previous row.
Compare row 2 with row 1
Compare row 3 with row 2
Also, if there is no difference, I need to make that column NULL. Eg: request_status_id of row 3 is same as that of row 2 so I need to update request_status_id of row 3 to NULL.
Is there a clean way to do this?
You can use the following UPDATE statement that employs LAG window function available from SQL Server 2012 onwards:
UPDATE #mytable
SET request_status_id = NULL
FROM #mytable AS m
INNER JOIN (
SELECT payment_history_id, request_status_id,
LAG(request_status_id) OVER(ORDER BY payment_history_id) AS prevRequest_status_id
FROM #mytable ) t
ON m.payment_history_id = t.payment_history_id
WHERE t.request_status_id = t.prevRequest_status_id
SQL Fiddle Demo here
EDIT:
It seems the requirement of the OP is to SET every column of the table
to NULL, in case the previous value is same as the current value. In this case the query becomes a bit more verbose. Here is an example with two columns being set. It can easily be expanded to incorporate any other column of the table:
UPDATE #mytable
SET request_status_id = CASE WHEN t.request_status_id = t.prevRequest_status_id THEN NULL
ELSE T.request_status_id
END,
request_entity_id = CASE WHEN t.request_entity_id = t.prevRequest_entity_id THEN NULL
ELSE t.request_entity_id
END
FROM #mytable AS m
INNER JOIN (
SELECT payment_history_id, request_status_id, request_entity_id,
LAG(request_status_id) OVER(ORDER BY payment_history_id) AS prevRequest_status_id,
LAG(request_entity_id) OVER(ORDER BY payment_history_id) AS prevRequest_entity_id
FROM #mytable ) t
ON m.payment_history_id = t.payment_history_id
SQL Fiddle Demo here

Subquery returned more than 1 value. this is not permitted when the subquery follows = or when the subquery is used as an expression?

I want to update multiple tables and values after inserting values in one table so I created a trigger. It works fine for inserts of one row, but as soon I insert more rows, SQL Server gives me following error:
subquery returned more than 1 value. this is not permitted when the subquery follows = or when the subquery is used as an expression?
Here is my trigger:
CREATE TRIGGER [dbo].[tbl_Sales_ForInsert]
ON [dbo].[SALES]
FOR INSERT
AS
BEGIN
DECLARE #ITEMMODEL varchar(100)
SELECT #ITEMMODEL = ITEM_MODEL FROM inserted
UPDATE SALES
SET PROFIT = TOTAL_PRICE - (SELECT QUANTITY FROM SALES WHERE ITEM_MODEL = #ITEMMODEL) * (SELECT RATE FROM ITEM_DETAILS WHERE ITEM_MODEL = #ITEMMODEL)
WHERE ITEM_MODEL = #ITEMMODEL
UPDATE ITEM_DETAILS
SET QUANTITY = QUANTITY - (SELECT QUANTITY FROM SALES WHERE ITEM_MODEL = #ITEMMODEL)
WHERE ITEM_MODEL = #ITEMMODEL
--UPDATE ITEM_DETAILS SET AMOUNT = AMOUNT - (SELECT RATE FROM ITEM_DETAILS WHERE ITEM_MODEL=#ITEMMODEL) * (SELECT QUANTITY FROM SALES WHERE ITEM_MODEL=#ITEMMODEL) where ITEM_MODEL=#ITEMMODEL
END
As I insert data in SALES table for 1st time the update got successful but for 2nd time it gives me above error remember ITEM_MODEL is foreign key constraint in SALES table.
I have been suffering with this error can anyone help me please?
Your fundamental flaw is that you seem to expect the trigger to be fired once per row - this is NOT the case in SQL Server. Instead, the trigger fires once per statement, and the pseudo table Inserted might contain multiple rows.
Given that that table might contain multiple rows - which one do you expect will be selected here??
SELECT #ITEMMODEL = ITEM_MODEL FROM inserted
It's undefined - you might get the values from arbitrary rows in Inserted.
You need to rewrite your entire trigger with the knowledge the Inserted WILL contain multiple rows! You need to work with set-based operations - don't expect just a single row in Inserted!
So in your case, your trigger code should look something like this:
CREATE TRIGGER [dbo].[tbl_Sales_ForInsert]
ON [dbo].[SALES]
FOR INSERT
AS
BEGIN
-- update the dbo.Sales table, set "PROFIT" to the difference of
-- TOTAL_PRICE and (QUANTITY * RATE) from the "Inserted" pseudo table
UPDATE s
SET s.PROFIT = i.TOTAL_PRICE - (i.QUANTITY * i.RATE)
FROM dbo.Sales s
INNER JOIN Inserted i ON i.ITEM_MODEL = s.ITEM_MODEL
-- update the dbo.ITEM_DETAILS table
UPDATE id
SET id.QUANTITY = id.QUANTITY - i.Quantity
FROM dbo.ITEM_DETAILS id
INNER JOIN Inserted i ON id.ITEM_MODEL = i.ITEM_MODEL
END
Marc_s is right about expecting the inserted pseudo table containing more than one row. There are instances that a query might work if a subquery was just limited to one row with a TOP(1).
UPDATE SALES
SET PROFIT = TOTAL_PRICE - (SELECT TOP(1) QUANTITY FROM SALES WHERE ITEM_MODEL = #ITEMMODEL)
* (SELECT TOP(1) RATE FROM ITEM_DETAILS WHERE ITEM_MODEL = #ITEMMODEL)
WHERE ITEM_MODEL = #ITEMMODEL

Sum of 2 values in a table

I have 2 Tables like below
Table - 1
Bank_Name
Bank_ACNO
Bank_Branch
Bank_Balance
Table - 2
Emp_ID
Amount_Paid
Table-1 contains unique records for each Bank ACNO. But Table 2 contain Multiple records. Now i want to update Table - 1 (Bank_Balance) With Sum(Table-1.Bank_Balance + Amount_Paid) where Table-1.Bank_ACNO=Table-2.Emp_ID.
I tried the below Query which did not Work.
UPDATE Bank_Master
SET Bank_Balance = ( Bank_Master.Bank_Balance
+ Order_Archieve_Temp.Amount_Paid )
OUTER JOIN Order_Archieve_Temp
ON Bank_Balance.Bank_ACNO=Order_Archieve_Temp.Emp_ID)
Here is the SQLFiddel Demo
Below is the Update Query which you can try :
Update T1
set T1.Bank_Balance = t1.Bank_Balance + t2.Amount_Paid
FROM TABLE1 T1,
(select Emp_ID,sum(Amount_Paid) as Amount_Paid
from Table2
group by Emp_ID ) as T2
WHERE T1.Bank_ACNO = T2.Emp_ID
If that's going to remain your table design, you better keep your database under really tight control: in most such circumstances, applications that have to determine a balance will do so by calculating it on-the-fly from some known and well-controlled state (say, from the last statement date) as a sum of that balance, and all the transactions that have occurred after then.
The current design appears vulnerable to miscalculation of the balance, and continued persistence of that error into the future.
Are there any possible concurrency issues here (could multiple parties possibly be executing this same statement from different connections?). What is your transaction isolation level?
Try this query:
BEGIN TRAN;
UPDATE t1
SET Bank_Balance = t1.Bank_Balance + ISNULL(x.Total_Amount_Paid,0)
-- or
-- SET Bank_Balance = ISNULL(t1.Bank_Balance,0) + ISNULL(x.Total_Amount_Paid,0)
-- or
-- SET Bank_Balance = NULLIF(ISNULL(t1.Bank_Balance,0) + ISNULL(x.Total_Amount_Paid,0), 0)
FROM dbo.Table1 t1
OUTER APPLY
(
SELECT SUM(t2.Amount_Paid) AS Total_Amount_Paid
FROM dbo.Table2 t2
WHERE t1.Bank_ACNO = t2.Emp_ID
) x
ROLLBACK
-- COMMIT

Resources