What's wrong with this DB2 SQL Query? - sql

SELECT
getOrgName(BC.ManageOrgID),
COUNT(CASE WHEN (EXISTS (SELECT FO.OBJECTNO FROM FLOW_OBJECT FO WHERE FO.ObjectNo=CR.SerialNo) AND NVL(CR.FinallyResult,'') IN ('01','02','03','04','05')) THEN BC.ManageOrgID ELSE NULL END)
FROM
BUSINESS_CONTRACT BC,
CLASSIFY_RECORD CR
WHERE
CR.ObjectType='BusinessContract'
AND CR.ObjectNo=BC.SerialNo
GROUP BY BC.ManageOrgID, CR.SerialNo, CR.FinallyResult
The error message I receive is:
11:01:32 [SELECT - 0 row(s), 0.000 secs] [Error Code: -112, SQL State: 42607] DB2 SQL Error: SQLCODE=-112, SQLSTATE=42607, SQLERRMC=SYSIBM.COUNT, DRIVER=3.57.82
... 1 statement(s) executed, 0 row(s) affected, exec/fetch time: 0.000/0.000 sec [0 successful, 0 warnings, 1 errors]

"The operand of the column function name (in your case, count) includes a column function, a scalar fullselect, or a subquery." DB2 doesn't allow this. See the documentation on SQL112 for more.
I'm not really sure how to fix your query but perhaps you can try the HAVING clause after GROUP BY.

Here is one way to rework the query:
SELECT
getOrgName( BC.ManageOrgID ),
COUNT( FO.ObjectNo ) AS objectcount
FROM BUSINESS_CONTRACT BC
INNER JOIN CLASSIFY_RECORD CR
ON CR.ObjectNo = BC.SerialNo
AND CR.ObjectType = 'BusinessContract'
AND CR.FinallyResult IN ( '01','02','03','04','05' )
INNER JOIN FLOW_OBJECT FO
ON FO.ObjectNo = CR.SerialNo
GROUP BY BC.ManageOrgID
;

Related

Clickhouse Cross join workaround?

I am trying to calculate the percentage of faulty transaction statuses per IP address in Clickhouse.
SELECT
c.source_ip,
COUNT(c.source_ip) AS total,
(COUNT(c.source_ip) / t.total_calls) * 100 AS percent_faulty
FROM sip_transaction_call AS c
CROSS JOIN
(
SELECT count(*) AS total_calls
FROM sip_transaction_call
) AS t
WHERE (status = 8 OR status = 9 or status = 13)
GROUP BY c.source_ip
Unfortunately Clickhouse rejects this with:
"Received exception from server (version 20.8.3):
Code: 47. DB::Exception: Received from 127.0.0.1:9000. DB::Exception: Unknown identifier: total_calls there are columns: source_ip, COUNT(source_ip)."
I tried various workarounds for the "invisible" alias, but failed. Any help would be greatly appreciated.
SELECT
source_ip,
countIf(status = 8 OR status = 9 or status = 13) AS failed,
failed / count() * 100 AS percent_faulty
FROM sip_transaction_call
GROUP BY source_ip
If you have a GROUP BY clause, you can only use columns you are grouping by (ie. c.source_ip) - for others you need an aggregate function.
Clickhouse is not too helpful here - for almost any other engine you would get a more meaningful error. See https://learnsql.com/blog/not-a-group-by-expression-error/.
Anyway, change grouping to GROUP BY c.source_ip, t.total_calls to fix it.

Case Statement in SQL Query Issue

I'm trying to run a SQL query but an error happens when I run it.
Error:
[Code: -811, SQL State: 21000]
The result of a scalar fullselect, SELECT INTO statement, or VALUES INTO statement is more than one row..
SQLCODE=-811, SQLSTATE=21000, DRIVER=4.19.49
This is the SQL query that I am trying to run, I believe there is a problem with my CASE statement, I'm running out of solution. Please help, thanks a lot!
SELECT
ES.SHPMNT_REF,
(CASE
WHEN (ES.SERVICE_PROVIDER_NAME) IS NULL
THEN (SELECT BRDB.EXPORT_ONHAND.SERVICE_PROVIDER_NAME
FROM BRDB.EXPORT_ONHAND
WHERE BRDB.EXPORT_ONHAND.SHPMNT_REF = ES.SHPMNT_REF)
ELSE (ES.SERVICE_PROVIDER_NAME)
END) AS SP
FROM
BRDB.EXPORT_SHIPMENT ES
WHERE
ES.DATE_CREATE > CURRENT TIMESTAMP - 30 DAYS
I think this is what you are after. Joining on the table data you might need, then letting COALESCE check for null and get the other data if it is.
SELECT
ES.SHPMNT_REF,
COALESCE(ES.SERVICE_PROVIDER_NAME, OH.SERVICE_PROVIDER_NAME) AS SP
FROM BRDB.EXPORT_SHIPMENT ES
LEFT JOIN BRDB.EXPORT_ONHAND AS OH
ON ES.SHPMNT_REF = OH.SHPMNT_REF
WHERE
ES.DATE_CREATE > CURRENT TIMESTAMP - 30 DAYS
Maybe you should put inside the case:
THEN (SELECT TOP 1 BRDB.EXPORT_ONHAND.SERVICE_PROVIDER_NAME
The error is thrown because your subquery returns multiple values.
The best way would be joining the two table first and then get the value you need when the value is NULL.
That should work:
SELECT
ES.SHPMNT_REF
,CASE
WHEN ES.SERVICE_PROVIDER_NAME IS NULL
THEN EO.SERVICE_PROVIDER_NAME
ELSE ES.SERVICE_PROVIDER_NAME
END AS 'SP'
FROM BRDB.EXPORT_SHIPMENT ES
LEFT JOIN BRDB.EXPORT_ONHAND EO
ON ES.SHPMNT_REF = EO.SHPMNT_REF
WHERE ES.DATE_CREATE > CURRENT TIMESTAMP - 30 DAYS

Hive summary function inside case statement

I am trying to write a simple Hive query:
select sum(case when pot_sls_q > 2* avg(pit_sls_q) then 1 else 0)/count(*) from prd_inv_fnd.item_pot_sls where dept_i=43 and class_i=3 where p_wk_end_d = 2014-06-28;
Here pit_sls_q and pot_sls_q both are columns in the Hive table and I want proportion of records which have pot_sls_q more than 2 times average of pit_sls_q. However I get error:
FAILED: SemanticException [Error 10128]: Line 1:95 Not yet supported place for UDAF 'avg'
To fool around I even tried using some window function:
select sum(case when pot_sls_q > 2* avg(pit_sls_q) over (partition by dept_i,class_i) then 1 else 0 end)/count(*) from prd_inv_fnd.item_pot_sls where dept_i=43 and class_i=3 and p_wk_end_d = '2014-06-28';
which is fine considering the fact filtering or partitioning the data on same condition is "same" data essentially but even with this I get error:
FAILED: SemanticException [Error 10002]: Line 1:36 Invalid column reference 'avg': (possible column names are: p_wk_end_d, dept_i, class_i, item_i, pit_sls_q, pot_sls_q)
please suggest right way of doing this.
You are using AVG inside SUM which won't work (along with other syntax errors).
Try analytic AVG OVER () this:
select sum(case when pot_sls_q > 2 * avg_pit_sls_q then 1 else 0 end) / count(*)
from (
select t.*,
avg(pit_sls_q) over () avg_pit_sls_q
from prd_inv_fnd.item_pot_sls t
where dept_i = 43
and class_i = 3
and p_wk_end_d = '2014-06-28'
) t;

Update SQL Server two statements

UPDATE ADDRESS
SET ADDRESS.LATITUDE = b.latitude,
ADDRESS.LONGITUDE= b.LONGITUDE
FROM POSTAL_CODE_LOOKUP b
WHERE ADDRESS.postal_cd = b.POSTALCODE
AND (address.LATITUDE != b.LATITUDE OR address.LONGITUDE !=b.LONGITUDE)
11:20:23 [BEGIN - 2454 row(s), 0.437 secs] Command processed
11:20:23 [BEGIN - 2454 row(s), 0.437 secs] Command processed
... 2 statement(s) executed, 4908 row(s) affected, exec/fetch time: 0.874/0.000 sec [2 successful, 0 warnings, 0 errors]
After executing the update I run the SQL below and get 2454 records.
select
a1.POSTAL_CD, b.POSTALCODE,
a1.LATITUDE, b.LATITUDE,
a1.LONGITUDE, b.LONGITUDE
from
ADDRESS a1, POSTAL_CODE_LOOKUP b
where
a1.postal_cd = b.postalcode
and (a1.LATITUDE != b.LATITUDE or a1.LONGITUDE != b.LONGITUDE);
Yes I have committed, and the records haven't changed. I don't understand why the update is being read as 2 statements. I don't understand why it's not updating.
How should I be writing this update statement?
Your ADDRESS table must have Update trigger, that's why there is a second statement about 2454 rows.
The amount updated is just 2454 rows, the same number You select after.
You have multiple rows in your join for one postal code i think
Use the below script to update the Address table .
UPDATE a
SET a.LATITUDE = b.latitude,
a.LONGITUDE= b.LONGITUDE
FROM [ADDRESS] a
JOIN POSTAL_CODE_LOOKUP b
ON a.postal_cd = b.POSTALCODE
WHERE (a.LATITUDE != b.LATITUDE or a.LONGITUDE !=b.LONGITUDE)

How should I create a temporary table when Union is used?

I can't use Dynamic Value bcoz of Error stating
"Lookup Error - SQL Server Database Error: Cannot perform an aggregate function on an expression containing an aggregate or a subquery."
Here is the Scenario :
Query 1
select pr.PRDCT,sum(CASE when pr.DEFINITIONCD='NOP' and pr.PERIOD='D' then pr.PRAMOUNT else 0 END)
as 'NOP D' from PRODUCTWISE_REPORT pr group by pr.PRDCT
Query 2
select DEFINITIONTYPECD from REPORTKPIMAPTXN where DEFINITIONTYPECD='NOP' and REPORTSEQ = (select REPORTSEQ from report_m where REPORTCD='MIS_Product_Wise_Report')
Query 2 returns 'NOP'
so when I put Query 2 in Query 1 for 'NOP', it throws Error
How to resolve this when I've to User Dynamic Query 2 ?
Your second query looks it could be rewritten with a join instead of that subselect. something like this. Of course you are still going to have some issues because your first query has two columns and this has only 1 column. You will have to add another column (can be NULL) to this query before the UNION will actually work.
select r.DEFINITIONTYPECD
from REPORTKPIMAPTXN r
INNER JOIN report_m m on m.REPORTSEQ = r.REPORTSEQ
where DEFINITIONTYPECD = 'NOP'
and r.REPORTCD = 'MIS_Product_Wise_Report'