DB2 merge upsert gets 'Row not found for MERGE' error - db2

I am trying to do a basic upsert on an iSeries db2 with the MERGE statement, similar to as described in Does DB2 have an "insert or update" statement? and http://db2performance.blogspot.com/2011/12/merge-make-your-upserts-quick.html. When executed, it gives me Row not found for MERGE. SQLSTATE=02000 instead of inserting the row. Since I have when not matched then insert in the statement, why will it return an error instead of inserting? I looked all over SO and didn't see this particular issue.
Here is the statement I'm using:
merge into UFDFTRN as T using (
select * from UFDFTRN
where DFCNO = 354 and DFINV = 1179 and DFLC = 1 and DFDATE = '2017-01-31'
and DFSPLT = 0 and DFSEQ = 100
) as S on (
T.DFCNO = S.DFCNO and T.DFINV = S.DFINV and T.DFDATE = S.DFDATE and
T.DFSPLT = S.DFSPLT and T.DFSEQ = S.DFSEQ
) when matched then
update set DFSEQ = 1000, DFTRAN = 0, DFITEM = 'F224', DFRITM = '0',
DFDESC = 'DAIRY VTM PREMIX', DFQTY = 3, DFUM = '',DESIQU = 0, DFRTQU = 3,
DFUPR = 0, DFCTUP = 0, DFUCST = 0, DFOUCST = 0, DFAMT = 0, DFOAMT = 0, DFCODE = '',
DFURAT = '', DFCGCD = '0', DFCTNO = 0, DFADJITM = '', DFADJPCT = 0, DFMNFITM = '',
DFMNFRAT = '', DFMNFQTY = '0', DFMNFTQTY = '0'
when not matched then
insert (DFCNO, DFINV, DFLC, DFDATE, DFSPLT, DFSEQ, DFTRAN, DFITEM, DFRITM, DFDESC,
DFQTY, DFUM, DFSIQU, DFRTQU, DFUPR, DFCTUP, DFUCST, DFOUCST, DFAMT, DFOAMT, DFCODE,
DFURAT, DFCGCD, DFCTNO, DFADJITM, DFADJPCT, DFMNFITM, DFMNFRAT, DFMNFQTY, DFMNFTQTY
) values (
354, 1179, 1, '2017-01-31', 0, 1000, 0, 'F224', '0', 'DAIRY VTM PREMIX', 3, '', 0,
3, 0, 0, 0, 0, 0, 0, '', '', '0', 0, '', 0, '', '', '0', '0'
)

It probably should look more like this:
merge into UFDFTRN as T using (
select 354 DFCNO, 1179 DFINV, 1 DFLC, '2017-01-31' DFDATE, 0 DFSPLT, 100 DFSEQ
, 'DAIRY VTM PREMIX' f1 -- all other columns you might need
from sysibm.sysdummy1
) as S
on (
T.DFCNO = S.DFCNO and T.DFINV = S.DFINV and T.DFDATE = S.DFDATE and
T.DFSPLT = S.DFSPLT and T.DFSEQ = S.DFSEQ
)
when matched then
update set T.DFSEQ = S.DFSEQ, T.DFTRAN = S.DFTRAN, -- etc. etc.
when not matched then
insert (DFCNO, DFINV, ... -- etc. etc.
) values (
S.DFSNO, S.DFINV, ..., S.F1, ...-- etc. etc.
)
PS. Not tested.

Mustaccio has the right format for the merge...
But as I commented, that's a really funny way to use merge.
Personally, for a 1 time thing, I would have just
update UFDFTRN
set (DFCNO, DFINV, DFLC, DFDATE, DFSPLT, DFSEQ, DFTRAN, DFITEM, DFRITM, DFDESC,
DFQTY, DFUM, DFSIQU, DFRTQU, DFUPR, DFCTUP, DFUCST, DFOUCST, DFAMT, DFOAMT, DFCODE,
DFURAT, DFCGCD, DFCTNO, DFADJITM, DFADJPCT, DFMNFITM, DFMNFRAT, DFMNFQTY, DFMNFTQTY
) = (
354, 1179, 1, '2017-01-31', 0, 1000, 0, 'F224', '0', 'DAIRY VTM PREMIX', 3, '', 0,
3, 0, 0, 0, 0, 0, 0, '', '', '0', 0, '', 0, '', '', '0', '0'
)
where DFCNO = 354 and DFINV = 1179 and DFLC = 1 and DFDATE = '2017-01-31'
and DFSPLT = 0 and DFSEQ = 100
And if that failed with record not found, simply changed the update to an insert
insert into UFDFTRN
(DFCNO, DFINV, DFLC, DFDATE, DFSPLT, DFSEQ, DFTRAN, DFITEM, DFRITM, DFDESC,
DFQTY, DFUM, DFSIQU, DFRTQU, DFUPR, DFCTUP, DFUCST, DFOUCST, DFAMT, DFOAMT, DFCODE,
DFURAT, DFCGCD, DFCTNO, DFADJITM, DFADJPCT, DFMNFITM, DFMNFRAT, DFMNFQTY, DFMNFTQTY
) values (
354, 1179, 1, '2017-01-31', 0, 1000, 0, 'F224', '0', 'DAIRY VTM PREMIX', 3, '', 0,
3, 0, 0, 0, 0, 0, 0, '', '', '0', 0, '', 0, '', '', '0', '0'
)

This use case is not unusual at all. This is the most basic use case for merge imo. You're trying to update or insert into 1 table. It really should be easier but the solution is to put any where clause in the on () portion of the statement and it starts working as expected. (worked db2 luw 10.5 at least.. I have the exact same situation) Merge apparently can't handle the using () portion's where clause. It only sees what's in on () portion for the update/insert criteria. Don't follow sysdummy1 answer as that isn't determining if the data actually exists in the target table it's just text. I don't want to write an insert and check failure because it will cause the app to throw an error and I really shouldn't have to trap the error and do that code if db2 has this feature.

Related

how to change mysql query to mongodb query

I am trying to change that mysql query to mongodb format. I can't find an answer on how to do it. Please suggest a solution.
I've tried several ways, but it doesn't work, please help
I know I have to use a aggregate query, but it's difficult because I have a lot of subqueries. How should I configure the stage?
SELECT #rowcnt := COUNT(*) AS cnt
, SUM(keywordcount) AS total_k_count
, SUM(exposecount) AS total_exp, SUM(clickcount) AS total_cc
, IF( SUM(exposecount) = 0, 0, ROUND((SUM(clickcount) / SUM(exposecount))* 100, 2) ) AS total_cr
, IF( SUM(clickcount) = 0, 0, ROUND(SUM(cost) / SUM(clickcount)) ) AS total_ccost
, ROUND(SUM(cost)) AS total_cost
, SUM(COUNT) AS total_count, SUM(directcount) AS total_d_count, SUM(indirectcount) AS total_ind_count
, IF( SUM(clickcount) = 0, 0, ROUND( ( SUM(COUNT) / SUM(clickcount) ) * 100, 2) ) AS total_con_r
, IF( SUM(COUNT) = 0, 0, ROUND((SUM(cost) / SUM(COUNT))) ) AS total_con_expense
, SUM(conversioncost) AS total_con_cost, SUM(conversiondirectcost) AS total_con_d_cost, SUM(conversionindirectcost) AS total_con_ind_cost
, IF( SUM(cost) = 0, 0, ROUND( ( SUM(conversioncost) / SUM(cost) * 100 ) ) ) AS total_roas
FROM (
SELECT a.s_date
, a.master_id, REPLACE( c.media_name, '\'', '\`' ) AS media_name, a.media_code
, b.keywordcount, SUM(a.exposecount) AS exposecount, SUM(a.clickcount) AS clickcount, SUM(a.cost) AS cost
, IF( SUM(a.exposecount) = 0, 0, ROUND((SUM(a.clickcount) / SUM(a.exposecount))* 100, 2) ) AS clickrate
, IF( SUM(a.clickcount)= 0, 0, ROUND( (SUM(a.cost) / SUM(a.clickcount)) , 2) ) AS clickcost
, b.count, b.directcount, b.indirectcount
, IF( SUM(a.clickcount) = 0, 0, ROUND((b.count / SUM(a.clickcount))* 100, 2) ) AS conversionrate
, IF( b.count = 0, 0, ROUND((SUM(a.cost) / b.count)) ) AS conversionexpense
, b.conversioncost, b.conversiondirectcost, b.conversionindirectcost
, IF( SUM(a.cost) = 0, 0, ROUND(( b.conversioncost / SUM(a.cost)) * 100) ) AS roas
FROM TMP_Report AS a
LEFT OUTER JOIN (
SELECT nrc.media_code, COUNT(*) AS keywordcount, nrc.master_id, SUM(nrc.count) AS COUNT, SUM(nrc.directcount) AS directcount, SUM(nrc.indirectcount) AS indirectcount
, SUM(nrc.conversioncost) AS conversioncost, SUM(nrc.conversiondirectcost) AS conversiondirectcost, SUM(nrc.conversionindirectcost) AS conversionindirectcost
FROM (
SELECT nrc.media_code, nrc.s_date, nrc.master_id, nrc.keyword_id, SUM(nrc.count) AS COUNT, SUM(nrc.directcount) AS directcount, SUM(nrc.indirectcount) AS indirectcount
, SUM(nrc.cost) AS conversioncost, SUM(nrc.directcost) AS conversiondirectcost, SUM(nrc.indirectcost) AS conversionindirectcost
FROM TMP_ReportConv AS nrc
GROUP BY nrc.master_id, nrc.keyword_id, media_code, s_date
) AS nrc
INNER JOIN autoanswer.calendar AS c2 ON nrc.s_date = c2.cal_date
GROUP BY nrc.master_id, nrc.media_code
) AS b ON a.master_id = b.master_id AND a.media_code = b.media_code
LEFT OUTER JOIN naver.mst_media c ON a.media_code = c.media_id
WHERE a.s_date BETWEEN $get_s_date AND $get_e_date
GROUP BY a.master_id, a.media_code
) AS m;
I am not going to do your job, but this could be a starting point:
db.TMP_Report.aggregate([
{
$group: {
_id: {master_id: "$master_id", media_code: "$media_code"},
count: { $count: {} },
clickcount: { $sum: "$clickcount" },
exposecount: { $sum: "$exposecount" }
}
},
{
$set: {
total_cr: { $round: [{ $multiply: [{ $divide: ["$clickcount", {$cond: ["$exposecount", "$exposecount", null]}] }, 100] }, 2] }
}
}
])

Perl DBI 2 dynamic arrays in 1 query

I currently have a webpage with 2 multiselect boxes that returns 2 different strings, which will be used in my SQL queries.
I am currently only using 1 string in my queries, but wish to add another and am unsure of where to go from here.
I have the string being created into an array
#sitetemp = split ',', $siteselect;
my $params = join ', ' => ('?') x #sitetemp;
and am able to use a query with $params
$mysql_inquire = "SELECT starttime, SUM(duration) FROM DB WHERE feature = \"$key\" and starttime >= $start and starttime <= $end and site IN ($params) group by starttime order by starttime";
$sth = $DBH->prepare($mysql_inquire);
$sth->execute(#sitetemp);
Essentially my question is how could I do the same thing, using 2 different arrays?
I assume the line $sth->execute(#sitetemp, #otherarray); would not work.
Your approach will work.
You can pass as many arrays into a function as you want. Arrays are just lists of values.
Consider the following example:
sub foo {
print Dumper \#_;
}
my #a = ( 1, 2, 3 );
my #b = ( 4, 5, 6 );
foo( #a, #b, ( 7, (8), 9, ( ( (10) ) ) ) );
This will print:
$VAR1 = [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10
];
When you say foo(#a, #b) it will just evaluate each array into a list. And you can combine as many lists as you want, they will always be flattened.

Expression of non-boolean type specified

Can't figure out why this query won't run, because its saying I don't have a Boolean statement where one should be.
The error I'm getting says:
An error occurred while executing the query.
An expression of non-boolean type specified in a context where a condition is expected, near 'AND'. (Microsoft SQL Server Report Builder)
Server Name: xxxxxxxxxx
Error Number: 4145
Severity: 15
State: 1
Line Number: 9
SELECT
REF_TPI_NPI_PHYS.MNE,
REF_TPI_NPI_PHYS.REFERRING,
RPT_MK_PRACT_PHYS_PT_CNT.COUNT_PTS AS TOTAL_PTS,
Sum(IIf(HBA1C_DATE IS NOT NULL, 1, 0)) AS COUNT_HBA1C,
Format((Sum(IIf(HBA1C_DATE IS NOT NULL, 1, 0)) / ([RPT_MK_PRACT_PHYS_PT_CNT].COUNT_PTS)), 'Percent') AS PANELED_HBA1C,
Format(Sum(IIf(HBA1C_VALUE IS NOT NULL AND IsNumeric(CAST(HBA1C_VALUE AS FLOAT)) AND CAST(HBA1C_VALUE AS FLOAT) <= 100, 1, 0))) / Sum(IIf(HBA1C_DATE IS NOT NULL, 1, 0)), 'Percent') AS HBA1C_COMP
Sum(IIf(LDL_DATE IS NOT NULL, 1, 0)) AS COUNT_LDL,
Format((Sum(IIf(LDL_DATE IS NOT NULL, 1, 0)) / ([RPT_MK_PRACT_PHYS_PT_CNT].COUNT_PTS)), 'Percent') AS PANELED_LDL,
Format(Sum(IIf(LDL_VALUE IS NOT NULL AND IsNumeric(CAST(LDL_VALUE AS FLOAT)) AND CAST(LDL_VALUE AS FLOAT) <= 100, 1, 0))) / Sum(IIf(LDL_DATE IS NOT NULL, 1, 0)), 'Percent') AS LDL_COMP
FROM
(
(
TBL_HBA1C_LDL LEFT JOIN TBL_REGISTRATION
ON CAST(RTRIM(LTRIM(TBL_HBA1C_LDL.PAT_MRN)) AS INTEGER) = TBL_REGISTRATION.MRN
)
LEFT JOIN
REF_TPI_NPI_PHYS
ON TBL_REGISTRATION.PCP = REF_TPI_NPI_PHYS.REFERRING
)
LEFT JOIN
RPT_MK_PRACT_PHYS_PT_CNT
ON TBL_REGISTRATION.PCP = RPT_MK_PRACT_PHYS_PT_CNT.PCP
GROUP BY
REF_TPI_NPI_PHYS.MNE,
REF_TPI_NPI_PHYS.REFERRING,
RPT_MK_PRACT_PHYS_PT_CNT.COUNT_PTS
ORDER BY
REF_TPI_NPI_PHYS.MNE,
REF_TPI_NPI_PHYS.REFERRING

What does the exclude_nodata_value argument to ST_DumpValues do?

Could anyone explain what the exclude_nodata_value argument to ST_DumpValues does?
For example, given the following:
WITH
-- Create a raster 4x4 raster, with each value set to 8 and NODATA set to -99.
tbl_1 AS (
SELECT
ST_AddBand(
ST_MakeEmptyRaster(4, 4, 0, 0, 1, -1, 0, 0, 4326),
1, '32BF', 8, -99
) AS rast
),
-- Set the values in rows 1 and 2 to -99.
tbl_2 AS (
SELECT
ST_SetValues(
rast, 1, 1, 1, 4, 2, -99, FALSE
) AS rast FROM tbl_1)
Why does the following select statement return NULLs in the first two rows:
SELECT ST_DumpValues(rast, 1, TRUE) AS cell_values FROM tbl_2;
Like this:
{{NULL,NULL,NULL,NULL},{NULL,NULL,NULL,NULL},{8,8,8,8},{8,8,8,8}}
But the following select statement return -99s?
SELECT ST_DumpValues(rast, 1, FALSE) AS cell_values FROM tbl_2;
Like this:
{{-99,-99,-99,-99},{-99,-99,-99,-99},{8,8,8,8},{8,8,8,8}}
Clearly, with both statements the first two rows really contain -99s. However, in the first case (exclude_nodata_value=TRUE) these values have been masked (but not replaced) by NULLS.
Thanks for any help. The subtle differences between NULL and NODATA within PostGIS have been driving me crazy for several days.

Merge command DB2 AIX (Update ok, insert not ok)

I'm currently struggeling with the merge command on a AIX DB2 9.7.
All I want to achieve is write a command which performes and Update when there is already a row with the primary keys checked and if not, then perform the Insert statement.
That is what I expect the merge command can be used for.
Select something
if exists then update
if not exists then isert
The Update statements works (I can see in my Toad) and of course in the database e.g. timestamp. But the Insert doesn't work.
Threre no syntay error shown, but no insert is made. Toad shows "executed successfully".
Any help is appreciated.
The WHERE clause shows the primary keys of the table.
MERGE INTO DSPTMCP.KENNZAHL_DEFINITION as KD
USING(Select NR_MANDANT, SL_GRUPPE_KENNZAHL, SL_KENNZAHL
FROM DSPTMCP.KENNZAHL_DEFINITION
WHERE NR_MANDANT = 5472 AND SL_GRUPPE_KENNZAHL = '_VBH' AND SL_KENNZAHL = 104) as KD1
ON(KD.NR_MANDANT = KD1.NR_MANDANT AND KD.SL_GRUPPE_KENNZAHL = KD1.SL_GRUPPE_KENNZAHL AND KD.SL_KENNZAHL = KD1.SL_KENNZAHL)
WHEN MATCHED Then
UPDATE SET
BEZ_KENNZAHL_ABS = 'MEFGA',
BEZ_KENNZAHL_REL = 'Aufgaben',
BEZ_EINHEIT_ABS = '%',
BEZ_EINHEIT_REL = '%',
SL_MODIFIZIERUNG = 3,
ANZ_NACHKOMMASTELLEN_ABS = 2,
ANZ_NACHKOMMASTELLEN_REL = 2,
KZ_QUALITAETSZIEL_ABS = 'H',
KZ_QUALITAETSZIEL_REL = 'H',
BEZ_ERMITTLUNGSFREQUENZ = 'Monatl.',
BEZ_ERMITTLUNGSART = 'Automat',
BEZ_DATENLIEFERANT = 'Geschäftsfelddaten',
TXT_QUELLINFORMATION = 'Geschäftsfelddaten',
TXT_KNZ_BESCHREIBUNG = 'Aufgaben',
FAK_REF_GEWICHT = 1,
KZ_HILFSGROESSE = 'N',
SL_GRUPPE_KENNZAHL_REL = 'ALLG',
SL_KENNZAHL_REL = 10,
FAK_ERGEBNIS_REL = 1,
BEZ_EINHEIT_QUELLE = '%',
FAK_UMRECHNUNG_QUELLE = 1,
KZ_REF_OHNE_VORZEICHEN = 'N'
WHEN Not MATCHED Then
INSERT (NR_MANDANT,
SL_GRUPPE_KENNZAHL,
SL_KENNZAHL,
SYS_DWH_TSP,
SL_MODIFIZIERUNG,
UID_ERFASSUNG,
TSP_ERFASSUNG,
UID_AENDERUNG,
TSP_AENDERUNG,
BEZ_EINHEIT_ABS,
ANZ_NACHKOMMASTELLEN_ABS,
SL_GRUPPE_KENNZAHL_REF,
SL_KENNZAHL_REF,
KZ_REF_OHNE_VORZEICHEN,
SL_REF_VERDICHTUNG,
BEZ_KENNZAHL_ABS,
BEZ_KENNZAHL_REL,
KZ_HIERARCHIESUMME,
KZ_QUALITAETSZIEL_ABS,
KZ_QUALITAETSZIEL_REL,
BEZ_ERMITTLUNGSFREQUENZ,
BEZ_ERMITTLUNGSART,
IHT_MINIMAL,
IHT_MAXIMAL,
IHT_MINIMAL_REL,
IHT_MAXIMAL_REL,
BEZ_DATENLIEFERANT,
TXT_QUELLINFORMATION,
DAT_ERFASSUNG_AB,
DAT_ERFASSUNG_BIS,
TXT_KNZ_BESCHREIBUNG,
FAK_REF_GEWICHT,
KZ_HILFSGROESSE,
SL_GRUPPE_KENNZAHL_REL,
SL_KENNZAHL_REL,
FAK_ERGEBNIS_REL,
BEZ_EINHEIT_QUELLE,
FAK_UMRECHNUNG_QUELLE,
BEZ_EINHEIT_REL,
ANZ_NACHKOMMASTELLEN_REL)
VALUES(5472,
'_VBH',
'104',
current timestamp,
3,
'AUTOMAT',
current timestamp,
'AUTOMAT',
current timestamp,
'%',
2,
null,
null,
'N',
null,
'Aufgaben',
'Aufgaben',
'N',
'H',
'H',
'Monatl.',
'Automat',
null,
null,
null,
null,
'Geschäftsfelddaten',
'Geschäftsfelddaten',
'01.01.2000',
'31.12.9999',
'Aufgaben',
1,
'N',
'ALLG',
'10',
1,
'%',
1,
'%',
2);
Problem solved. The target table coming from the using clause needn't to be empty.
Switched it to sysdummy and now it works.
Something like this
MERGE INTO DSPTMCP.KENNZAHL_DEFINITION as KD
USING(Select 5472 AS NR_MANDANT, '_KCR' AS SL_GRUPPE_KENNZAHL,
600 AS SL_KENNZAHL FROM sysibm.sysdummy1) as KD1
ON(KD.NR_MANDANT = KD1.NR_MANDANT AND KD.SL_GRUPPE_KENNZAHL = KD1.SL_GRUPPE_KENNZAHL AND KD.SL_KENNZAHL = KD1.SL_KENNZAHL)
WHEN MATCHED THEN