CASE, WHEN, THEN on UPDATE - postgresql

I have this issue where if there is no record in copy_on_write.id then the UPDATE listings SET images = (SELECT images FROM new_vals) runs and wipes out listings.images with nothing.
So, I am trying to use a condition to only run the UPDATE listings if copy_on_write.images exist.
right now I get:
psql:queries/copy-to-source.sh:20: ERROR: syntax error at or near "CASE"
LINE 10: CASE WHEN images <>
WITH
new_vals AS (
SELECT *
FROM copy_on_write
WHERE copy_on_write.posted_by = 102550922::text
AND copy_on_write.id = 4
),
updates AS (
SELECT images FROM new_vals,
CASE WHEN images <> ''
THEN UPDATE listings SET images = (SELECT images FROM new_vals)
END
)
SELECT internal_id FROM new_vals

You can use updates CTE like this:
...
updates AS (
UPDATE listings SET
images = new_vals.images
FROM new_vals
WHERE new_vals.images <> ''
)
....
Note, that:
Your new_vals CTE should always return maximum one record, otherwise this won't works correct.
Also this not updates listings table, if new_vals returns images column, but it is empty string (or null). If in such cases you need run update anyway, then remove WHERE new_vals.images <> '' at all.
And also, this statement will update all listings.images records. Do you really want this?

Related

Don't understand 'CREATE VIEW' must be the first statement in a query batch

I am trying to create a View for temporary data I only need during the SQL run.
I get the error:
"'CREATE VIEW' must be the first statement in a query batch."
I searched on that and see it was asked about on Stack Overflow already here: 'CREATE VIEW' must be the first statement in a query batch
However, my SQL code looks like it should but I still get the error. First, I create a table called #StatusTable but that table wasn't working like I wanted. So I tried creating a View.
DECLARE #DOC INT;
DECLARE #StatusTable TABLE
(
status VARCHAR(8000)
)
INSERT INTO #StatusTable
Select Status = ( select CONCAT(ls.ItemText, '/', st.ItemText ) as Status from Inmate_Legal_Status ils
Left join jt_list_items ls on ls.ItemID = ils.LegalStatusID
Left join jt_list_items st on st.ItemID = ils.StatusTypeId
where ArrestNo = #doc and ils.RecordDeleted = 0
order by ils.CreatedTime desc FOR XML PATH('')
)
-- table
USE #StatusTable;
GO
create view MyView as
Select Status = ( select CONCAT(ls.ItemText, '/', st.ItemText ) as Status from Inmate_Legal_Status ils
Left join jt_list_items ls on ls.ItemID = ils.LegalStatusID
Left join jt_list_items st on st.ItemID = ils.StatusTypeId
where ArrestNo = #doc and ils.RecordDeleted = 0
GO
I get three errors:
Incorrect syntax near GO.
'CREATE VIEW' must be the first statement in a query batch
Incorrect syntax near #StatusTable

Update columns based on different criteria using merge statement

So I am using the following merge statement to do an update and insert in one of my tables, however I would like to update another column in the Target table in addition to the one already in the statement. I'm just not sure if I can do that or how to go about it. What I want to do is add in something like
when MATCHED and Source.EventType='Change' Then UPDATE SET Target.DEDCAMT_1 = Source.EmpDedAmt
Can I do that in the same Merge statement?
MERGE dbo.BENTBL as Target
using dbo.BenPaycdUpdate as Source
ON Source.EmpID = Target.EMPLOYID AND Source.Paycode = Target.DEDUCTON
WHEN MATCHED AND source.EventType='Stop'
THEN UPDATE
SET INACTIVE = '1',
Target.DEDENDDT = Source.AsOfDate
WHEN NOT MATCHED BY Target
AND Source.PayCode <> 'FSAH'
THEN INSERT (EMPLOYID, DEDUCTON, INACTIVE, DEDBEGDT, DEDCAMNT_1)
VALUES (Source.EmpID, Source.Paycode,'0', Source.AsofDate,
CAST(REPLACE (REPLACE(ISNULL(source.EmpDed,0),',',''),'$','') AS numeric(19,5)));
You can move the condition from the merge to a case expression, like this:
MERGE dbo.BENTBL as Target
using dbo.BenPaycdUpdate as Source
ON Source.EmpID = Target.EMPLOYID AND Source.Paycode = Target.DEDUCTON
WHEN MATCHED THEN
UPDATE
SET INACTIVE = CASE WHEN source.EventType = 'Stop' THEN '1' ELSE INACTIVE END,
Target.DEDCAMT_1 = CASE WHEN source.EventType = 'Change' THEN Source.EmpDedAmt ELSE Target.DEDCAMT_1 END,
Target.DEDENDDT = Source.AsOfDate
WHEN NOT MATCHED BY Target AND Source.PayCode <> 'FSAH' THEN
INSERT (EMPLOYID, DEDUCTON, INACTIVE, DEDBEGDT, DEDCAMNT_1)
VALUES (Source.EmpID, Source.Paycode,'0', Source.AsofDate,
CAST(REPLACE (REPLACE(ISNULL(source.EmpDed,0),',',''),'$','') AS numeric(19,5)));

How to use CASE clause (DB2) to display values from a different table?

I'm working in a bank so I had to adjust the column names and information in the query to fit the external web, so if there're any weird mistakes know it is somewhat fine.
I'm trying to use the CASE clause to display data from a different table, I know this is a workaround but due to certain circumstances I'm obligated to use it, plus it is becoming interesting to figure out if there's an actual solution.
The error I'm receiving for the following query is:
"ERROR [21000] [IBM][CLI Driver][DB2] SQL0811N The result of a scalar
fullselect, SELECT INTO statement, or VALUES INTO statement is more
than one row."
select bank_num, branch_num, account_num, client_id,
CASE
WHEN exists(
select *
from bank.services BS
where ACCS.client_id= BS.sifrur_lakoach
)
THEN (select username from bank.services BS where BS.client_id = ACCS.client_id)
ELSE 'NONE'
END username_new
from bank.accounts accs
where bank_num = 431 and branch_num = 170
EDIT:
AFAIK we're using DB2 v9.7:
DSN11015 - DB21085I Instance "DB2" uses "64" bits and DB2 code release "SQL09075" with
level identifier "08060107".
Informational tokens are "DB2 v9.7.500.702", "s111017", "IP23287", and Fix Pack "5".
Use listagg function to include all results.
select bank_num, branch_num, account_num, client_id,
CASE
WHEN exists(
select *
from bank.services BS
where ACCS.client_id= BS.sifrur_lakoach
)
THEN (select LISTAGG(username, ', ') from bank.services BS
where BS.client_id = ACCS.client_id)
ELSE 'NONE'
END username_new
from bank.accounts accs
where bank_num = 431 and branch_num = 170

SELECT with substring in ON clause?

I have the following select statement in ABAP:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
INTO corresponding fields of table GT_INSTMUNIC_F
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN EVER AS EV on
MUNIC~POD = EV~VREFER(9).
"where EV~BSTATUS = '14' or EV~BSTATUS = '32'.
My problem with the above statement is that does not recognize the substring/offset operation on the 'ON' clause. If i remove the '(9) then
it recognizes the field, otherwise it gives error:
Field ev~refer is unknown. It is neither in one of the specified tables
nor defined by a "DATA" statement. I have also tried doing something similar in the 'Where' clause, receiving a similar error:
LOOP AT gt_instmunic.
clear wa_gt_instmunic_f.
wa_gt_instmunic_f-mandt = gt_instmunic-mandt.
wa_gt_instmunic_f-bis = gt_instmunic-bis.
wa_gt_instmunic_f-ab = gt_instmunic-ab.
wa_gt_instmunic_f-zzelecdate = gt_instmunic-zzelecdate.
wa_gt_instmunic_f-ZZCERTDATE = gt_instmunic-ZZCERTDATE.
wa_gt_instmunic_f-CONSYEAR = gt_instmunic-CONSYEAR.
wa_gt_instmunic_f-ZDIMO = gt_instmunic-ZDIMO.
wa_gt_instmunic_f-ZZONE_M = gt_instmunic-ZZONE_M.
wa_gt_instmunic_f-ZZONE_T = gt_instmunic-ZZONE_T.
wa_gt_instmunic_f-USAGE_M = gt_instmunic-USAGE_M.
wa_gt_instmunic_f-USAGE_T = gt_instmunic-USAGE_T.
temp_pod = gt_instmunic-pod.
SELECT vrefer
FROM ever
INTO wa_gt_instmunic_f-vrefer
WHERE ( vrefer(9) LIKE temp_pod ). " PROBLEM WITH SUBSTRING
"AND ( BSTATUS = '14' OR BSTATUS = '32' ).
ENDSELECT.
WRITE: / sy-dbcnt.
WRITE: / 'wa is: ', wa_gt_instmunic_f.
WRITE: / 'wa-ever is: ', wa_gt_instmunic_f-vrefer.
APPEND wa_gt_instmunic_f TO gt_instmunic_f.
WRITE: / wa_gt_instmunic_f-vrefer.
ENDLOOP.
itab_size = lines( gt_instmunic_f ).
WRITE: / 'Internal table populated with', itab_size, ' lines'.
The basic task i want to implement is to modify a specific field on one table,
pulling values from another. They have a common field ( pod = vrefer(9) ). Thanks in advance for your time.
If you are on a late enough NetWeaver version, it works on 7.51, you can use the OpenSQL function LEFT or SUBSTRING. Your query would look something like:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN ever AS ev
ON MUNIC~POD EQ LEFT( EV~VREFER, 9 )
INTO corresponding fields of table GT_INSTMUNIC_F.
Note that the INTO clause needs to move to the end of the command as well.
field(9) is a subset operation that is processed by the ABAP environment and can not be translated into a database-level SQL statement (at least not at the moment, but I'd be surprised if it ever will be). Your best bet is either to select the datasets separately and merge them manually (if both are approximately equally large) or pre-select one and use a FAE/IN clause.
They have a common field ( pod = vrefer(9) )
This is a wrong assumption, because they both are not fields, but a field an other thing.
If you really need to do that task through SQL, I'll suggest you to check native SQL sentences like SUBSTRING and check if you can manage to use them within an EXEC_SQL or (better) the CL_SQL* classes.

UPDATE with Aggregate SELECT - SET columns 0 when SELECT is empty

I have the following UPDATE statement
UPDATE stuff
SET stuff.total = t.total
FROM (
SELECT SUM(price) FROM things WHERE stuff_id = ? GROUP BY stuff_id
) t
WHERE stuff.id = ?
This works fine when there are actually rows in things, but when not no UPDATE is executed (which I guess makes sense). What would be an elegant way to set stuff.total to 0 in that case? I'd like to do it in one query.
I already tried SET stuff.total = coalesce(t.total, 0) but it had no effect.
You haven't used coalesce in the right place. Also, GROUP BY can be omitted. Try this query:
UPDATE stuff
SET stuff.total = t.total
FROM (
SELECT coalesce(SUM(price), 0) FROM things WHERE stuff_id = ?) t
WHERE stuff.id = ?