How to use CASE expression to update a table with inner queries - sql

I have used the following update query :
UPDATE datA_table T
SET T.VALUE=
(SELECT
CASE
WHEN t3.h1 =(t3.h2) and t3.h1=(t3.h3) THEN t3.h1
ELSE
Case
wHEN T3.h1 < > T3.h2 THEN T3.h2
ELSE
cASE
wHEN T3.h1 < > T3.h3 THEN T3.h3
eND
eND
END
from datA_table t3)T1
where t.time=t1.time and t.name=t1.name
But this is giving the following error:
Error report - SQL Error: ORA-00933: SQL command not properly ended
00933. 00000 - "SQL command not properly ended"
Is there any way to resolve this issue?

You can have many WHEN in each CASE, which is also likely to perform better than nested CASEs. I'm unfamiliar with the way you linked the updated table with the subselect (normally you can't refer to internal aliases in a subquery from outside), and don't know if it works at all, so I coded it in a way I know for sure it works:
UPDATE datA_table T
SET T.VALUE=
(SELECT
CASE
WHEN t3.h1 =(t3.h2) and t3.h1=(t3.h3) THEN t3.h1
WHEN T3.h1 < > T3.h2 THEN T3.h2
wHEN T3.h1 < > T3.h3 THEN T3.h3
END
from datA_table t3
where t.id=t3.id AND T.name=T3.name
)
where <your condition for datA_table rows to be updated>
Update
I just noticed that both the table being modified and the table in the subquery are the same table, and that the joining condition is likely to be a key. Therefore, there is no need to specify a subquery at all. The following simpler UPDATE will do the same, but likely much faster (I also improved the CASE logic, as the first test was superfluous):
UPDATE datA_table
SET VALUE = CASE
WHEN h1 <> h2 THEN h2
WHEN h1 <> h3 THEN h3
ELSE h1
END
WHERE <your condition for rows to be updated>

The syntax is incorrect. Everything after the parenthesis ending the SELECT should be omitted.
The subselect takes the place of <expression> in
UPDATE data_table SET value = <expression>
By the way, The CASE construction is overly complicated; you could use a single CASE expression like in
CASE WHEN <condition1>
THEN <expression1>
WHEN <condition2>
THEN <expression2>
...
ELSE <expression>
END

Related

Redshift Correlated Subquery Internal Error

So I have a table of bids in Amazon Redshift. Each bid has a description and a user who made the bid, and for each bid I want to know if a user made a bid with the same description in the last 5 days.
The query looks like this:
select b1.bid_id, case when
exists(select b2.bid_id from dim_bid b2 WHERE b1.user_id = b2.user_id
and b2.bid_timestamp < b1.bid_timestamp and b2.bid_timestamp > b1.bid_timestamp - INTERVAL '5 day'
and b2.description = b1.description and b2.bid_timestamp > '2017-04-25') then 'good bid' else 'duplicate bid' END
from dim_bid b1
where b1.hidden
which doesn't work, giving the error: this type of correlated subquery is not supported due to internal error. However when I just add a "=True" at the end it works.
select b1.bid_id, case when
exists(select b2.bid_id from dim_bid b2 WHERE b1.user_id = b2.user_id
and b2.bid_timestamp < b1.bid_timestamp and b2.bid_timestamp > b1.bid_timestamp - INTERVAL '5 day'
and b2.description = b1.description and b2.bid_timestamp > '2017-04-25') then 'good bid' else 'duplicate bid' END
from dim_bid b1
where b1.hidden = True
Is this just a bug, or is there some deep reason why the first one can't be done?
I think the better way to write the query uses lag():
select b.*,
(case when lag(b.bid_timestamp) over (partition by b.description order by b.timestamp) > b.bid_timestamp - interval '5 day'
then 'good bid' else 'duplicate bid'
end)
from dim_bid b;
Try to run this first:
select b1.bid_id
from dim_bid b1
where b1.hidden
You will see that redshift will raise a different error(eg. WHERE must be type boolean...). So argument of where must be a boolean in order for the query to run. So when you add '=True' then argument is boolean and query runs. And when the query has correlated subquery and there is an invalid operation in the query I have noticed that redshift raises correlated subquery error. This might be due to the fact that redshift does not support some of the correlated subqueries(correlated subqueries redshift).
The docs state the following:
We recommend always checking Boolean values explicitly, as shown in the examples following. Implicit comparisons, such as WHERE flag or WHERE NOT flag might return unexpected results.
Reference: http://docs.aws.amazon.com/redshift/latest/dg/r_Boolean_type.html
I do not think this is necessarily a bug. I would recommend always checking boolean values as where b1.hidden is True. I have seen this error quite a few times when using correlated subqueries, but I have always been able to fix it when explicitly checking the boolean values using is true/false/unknown.

How to give change working of having function dynamicaly on executing an sql statement?

I'm having a Sql code like as follows
Select a.ItemCode, a.ItemDesc
From fn_BOM_Material_Master('A', #AsOnDate, #RptDate, #BranchID, #CompID)a
Left Outer Join fn_INV_AsOnDate_Stock(#StockDate, #AsOnDate, #RptDate, #BranchID, #CompID, #Finyear)b
On a.ItemCode=b.ItemCode and b.WarehouseCode<>'WAP'
and a.BranchID=b.BranchID and a.CompID=b.COmpID
Where a.ItemNatureCode = 'F' and a.BranchID = #BranchID and a.CompID = #CompID
Group by a.ItemCode, a.ItemDesc
Having sum(b.CBQty)<=0
Here the problem is that im passing an "#ShowZeroStock" value as as bit if the "#ShowZeroStock" value is '1' then Having should not be validated or (i.e: All values from the table should be returned including zero)
So How to change the query based on passed bit value "#ShowZeroStock"
I can Use "If else " condition at the top and remove having in else part, but for a lengthy query i can't do the same.
Is this the logic you want?
Having sum(b.CBQty) <= 0 or #ShowZeroStock = 1

Error on Oracle Case statement assigning value

I wanted to assign a value "F" to TBL_C.PAY_CODE when its value is T but I cant seem to find the error in this SQL statement. I don't want to use PL/SQL for this just normal SQL statement.
ERROR
ORA-00905: missing keyword
00905. 00000 - "missing keyword"
SQL CODE
SELECT
TBL_A.ACT_ID,
TBL_A.ACT_CODE,
TBL_A.ACT_DESC,
TBL_A.ACT_DIS_DESC,
TBL_B.ACTMAP_ID,
TBL_B.CLI_ID
FROM CACT TBL_A, CMACTM TBL_B, CMACTDM TBL_C
WHERE TBL_A.ACT_ID=TBL_B.ACT_ID AND B.ACTMAP_ID=TBL_C.ACTMAP_ID
AND TBL_C.CODE = 'Version64'
AND TBL_C.ID='100001000000001'
AND TBL_C.PAY_CODE= CASE
WHEN TBL_C.PAY_CODE='T' AND TBL_C.CODE ='Version64'
THEN TBL_C.PAY_CODE='F' <-- ERROR
else TBL_C.PAY_CODE='T'
END;
Update
This query is for retrieving one row which has the following table values. When users submit a button with the following values but with Pay_Code equal to T the row below should be retrieved. I cannot change the value of the pay_code because there are other problems that will be encountered.
Table TBL_C
ACTMAP_ID ID PAY_CODE CODE
100001000000100 100001000000001 F Version64
Original Query Used:
SELECT TBL_A.ACT_ID, TBL_A.ACT_CODE, TBL_A.ACT_DESC, TBL_A.ACT_DIS_DESC, TBL_B.ACTMAP_ID, TBL_B.CLI_ID
FROM CACT TBL_A, CMACTM TBL_B, CMACTDM TBL_C
WHERE TBL_A.ACT_ID=TBL_B.ACT_ID AND B.ACTMAP_ID=TBL_C.ACTMAP_ID
AND TBL_C.CODE =? (Value is Version64)
AND TBL_C.ID=? (Value is 100001000000001)
AND TBL_C.PAY_CODE=? (Either T or F but in the value is set to F)
SELECT TBL_A.ACT_ID, TBL_A.ACT_CODE, TBL_A.ACT_DESC, TBL_A.ACT_DIS_DESC, TBL_B.ACTMAP_ID, TBL_B.CLI_ID
FROM CACT TBL_A, CMACTM TBL_B, CMACTDM TBL_C
WHERE TBL_A.ACT_ID=TBL_B.ACT_ID AND B.ACTMAP_ID=TBL_C.ACTMAP_ID
AND TBL_C.CODE = 'Version64'
AND TBL_C.ID='100001000000001'
AND TBL_C.PAY_CODE= CASE
WHEN TBL_C.PAY_CODE='T' AND TBL_C.CODE ='Version64'
THEN 'F' <-------------
else 'T' <-------------
END;
Note: The fact you are comparing TBL_C.CODE = 'Version64' twice suggests a possible flaw in your logic....
Great question, dimas! I'm not clear on your desired logic, but it appears you want to return records where BL_C.PAY_CODE='T' and TBL_C.CODE ='Version64' or BL_C.PAY_CODE='F'. If this is the case, I would write it:
SELECT
TBL_A.ACT_ID,
TBL_A.ACT_CODE,
TBL_A.ACT_DESC,
TBL_A.ACT_DIS_DESC,
TBL_B.ACTMAP_ID,
TBL_B.CLI_ID
FROM CACT TBL_A, CMACTM TBL_B, CMACTDM TBL_C
WHERE TBL_A.ACT_ID=TBL_B.ACT_ID AND B.ACTMAP_ID=TBL_C.ACTMAP_ID
AND TBL_C.ID='100001000000001'
AND ((TBL_C.PAY_CODE='T' AND TBL_C.CODE ='Version64')
OR TBL_C.PAY_CODE='F');
If I have misread your desired outcome, please clarify and I'll update the answer.

HIVE - hive subquery is not working with case when statement with IN clause

I am trying to migrate data from mysql to hive.I am not able to write a subquery case when statement with IN clause.This is my query. Can you Please help in this regard. AM i not following the proper syntax .
CREATE TABLE HIVE_TPCE_TEMP.TMP_CDMA_CD AS
SELECT A.DRI,C.BOUND_ID,A.CT_ID,A.CD_ID,A.CID,
A.TID,A.TASK_SEQ_ID,A.DIV_ID,C.BLOCK_GROUP_ID,C.ZIP_CODE,C.ROAD_CATEGORY_ID,A.RXPOWER,"${hiveconf:C_CDMA_DEVICE_ONLINE_RXPOWER_METRIC_ID}" METRIC_ID,
CASE WHEN
((A.DRI,A.DIV_ID,A.RFID) in (SELECT DRI,DIV_ID,HOME_RFID FROM HIVE_TPCE_TEMP.TMP_HOME_NETWORKS)) THEN
CASE WHEN MODE IN ('A','N') THEN "${hiveconf:HAD}" ELSE "${hiveconf:HD}" END
WHEN (COALESCE(A.RFID,0) = 0) AND ((A.DRI,A.DIV_ID,D.FR,D.SUBBAND) IN (SELECT DRI,DIV_ID,HOME_FR,
HOME_SUBBAND FROM HIVE_TPCE_TEMP.TMP_HOME_NETWORKS))
THEN CASE WHEN MODE IN ('A','N') THEN "${hiveconf:HAD}" ELSE "${hiveconf:HD}" END
ELSE CASE WHEN MODE IN ('A','N') THEN "${hiveconf:PAI}" ELSE "${hiveconf:PDI}" END END HPDA_ID
FROM HIVE_TPCE.VW_CDMA_CD A INNER JOIN HIVE_TPCE.STG_CURRENT_FILES B
ON A.DRI = B.DRI AND A.SOURCE_FILE_ID = B.SOURCE_FILE_ID
INNER JOIN
HIVE_TPCE.WRK_LOCATION C
ON A.DRI = C.DRI AND A.LOCATION_ID = C.LOCATION_ID
INNER JOIN
HIVE_TPCE.LU_RADIO D
ON A.RADIO_ID = D.RADIO_ID WHERE A.CID > 0 AND D.MODE IN ('A','N') AND A.RXPOWER IS NOT NULL AND A.CALL_RESULT_ID BETWEEN 1 AND 16;
My error signature is
FAILED: ParseException line 10:42 mismatched input ',' expecting ) near 'DRI' in expression specification
According to the Hive Language Manual: "Hive supports subqueries only in the FROM clause".
Your CASE WHEN is part of the SELECT clause, but it includes includes a SELECT subquery. Seems like that is not supported, so your syntax is not correct (in Hive).
Perhaps you could stage the data in MySQL using the query you have and then load it into Hive using a simple SELECT without CASE WHEN?
See official document.
It says
Assumptions
We plan to limit the scope with the following assumptions and limitations.
Subqueries could only be top-level expressions in SELECT. That is, subqueries in complex expressions, aggregates, UDFs, etc. will not be supported for now

Selects in Joins

I have query
UPDATE THD
SET RepostFlag = 'Y'
,RunListNoRetroPolicyPrepay = ?
,RetroObject = ?
FROM TranHead AS THD
JOIN (
SELECT CustPolicyNo AS CustPolicyNo
,MIN(PremPeriod) AS PremPeriod
FROM TranHead
WHERE RepostFlag = 'Y'
AND PayoutTypeNo = ?
GROUP BY CustPolicyNo
) AS THDToBeReposted ON THD.CustPolicyNo = THDToBeReposted.CustPolicyNo
WHERE THD.RepostFlag = 'N'
AND THD.PremPeriod > THDToBeReposted.PremPeriod
fails in H2 with following message
Table "THD" not found;
I looked at http://www.h2database.com/html/grammar.html#table_expression to see if H2 supports selects in join. It appears it does. Maybe I am missing something when looking at the grammar, but it seems to me that the query should work in H2.
Anyone see what is wrong?
Thanks.
I don't believe FROM is allowed in the UPDATE syntax.
You can't update an alias, you need to have the table name specified.
Complementary to other answers, JOIN (just as FROM) is not allowed in UPDATE for H2. It would be allowed in a sub query.
Essentially, stick to the basic syntax:
UPDATE SomeTable as SomeAlias
SET SomeField = ?
WHERE (%GoWild%)
Whether or not you need the alias is up to your where clause.
Reference: http://www.h2database.com/html/grammar.html#update