Character string buffer too small - sql

I have select:
select v.accs, v.currency,v.amount,v.drcr_ind, count(*) qua,wm_concat(ids) npx_IDS,
wm_concat(px_dtct) npx_DTCT
from table v
group by accs, currency, amount, drcr_ind
but i get error ORA-06502: PL/SQL: : character string buffer too small if i'll remove one string, because sometimes (when v.accs= 3570) count(*) = 215
but when i try to skip using wm_concat for v.accs= 3570 for example this way:
select v.accs, v.currency,v.amount,v.drcr_ind, count(*) qua,wm_concat(ids) npx_IDS,
(case when v.accs = 3570 then wm_concat(px_dtct) else 'too many' end) npx_DTCT
from table v
group by accs, currency, amount, drcr_ind
i still have the same error message. But why?

You concatenate results from a query. This query can result in a lot of rows so eventually you will run out of string length. Maybe concatenation is not the way to go here. Depends on what you want to achieve of course.

Why? Because you still use wm_concat for accs=3570... swap the THEN and ELSE part of your CASE expression
select v.accs, v.currency,v.amount,v.drcr_ind, count(*) qua,wm_concat(ids) npx_IDS,
(case when v.accs = 3570 then 'too many' else wm_concat(px_dtct) end) npx_DTCT
from table v group by accs, currency, amount, drcr_ind

First, as it has already been told, you have to switch then and else clauses in your query.
Then, I guess you should also similarily process your second wm_concat, the one that works with ids.
select v.accs, v.currency,v.amount,v.drcr_ind, count(*) qua,
(case when v.accs = 3570 then 'too many' else wm_concat(ids) end) npx_IDS,
(case when v.accs = 3570 then 'too many' else wm_concat(px_dtct) end) npx_DTCT
from table v
group by accs, currency, amount, drcr_ind
And, finally, why do you think that only v.accs = 3570 is able to bring 06502 error in front of you? I suppose you should handle all of them.

Related

Postgres group by having at least 1 row with status='started'

I need to perform a group by and only including if at least one observation matches the constraint. Like I have tried to describe below.
SELECT {some variables}
FROM my_table
GROUP BY A
HAVING {at least 1 row with status='started'}
My initial guess to replace was "at least 1 row with status='started'" was "bool_or(status='started')". Which doesn't work.
Do any of you have a sugestion?
EDIT:
SELECT {some variables}
FROM my_table
GROUP BY A
HAVING bool_or(status='started');
Works fine. The reason it not work for me, was that I used the wrong quotation mark. Thanks for your help and sorry for the inconvenience.
having bool_or(status = 'started') is a nice option in Postgres, and probably your best pick here.
It is actually equivalent to:
having max( (status = 'started')::int ) = 1
For the sake of completness: in standard SQL, you would phrase this with a case expression:
having max(case when status = 'started' then 1 end) = 1

AND OR SQL operator with multiple records

I have the following query where if brand1/camp1 taken individually, query returns the correct value but if I specify more than one brand or campaigns, it returns some other number and I am not sure what the math is behind that. It is not the total of the two either.
I think it is IN operator that is specifying OR with "," as opposed to what I require it to do which is consider AND
select campaign,
sum(case when campaign in ('camp1', 'camp2') and description in ('brand1', 'brand2') then orders else 0 end) as brand_convs
from data.camp_results
where campaign in ('camp1', 'camp2') and channel='prog' and type='sbc'
group by campaign
having brand_convs > 0
order by brand_convs desc;
Any thoughts?
The problem is in the IN part as you suspected: The two IN operators do not affect eachother in any way, so campaign can be camp1 while description is brand2.
If your DBMS supports multiple columns in an IN statement, you use a single IN statement:
SELECT campaign, SUM(
CASE WHEN (campaign, description) IN (
('camp1', 'brand1'),
('camp2', 'brand2')
) THEN orders ELSE 0 END
) [rest of query...]
If not, you're probably going to have to use ANDs and ORs
SELECT campaign, SUM(
CASE WHEN
(campaign='camp1' AND description='brand1')
OR (campaign='camp2' AND description='brand2')
THEN orders ELSE 0 END
) [rest of query...]

changing positions of sql query results

The title is not claryifying my problem but this is how i could describe it.
I have a query which returns the following result :
and i was wondering if there is a way to reduce the number of lines from three to one having all the three no null values ( 400, 1000 and 21820 in one line ) with banquet as description.
Thank you for reading.
PS: this is just a capture of a part of the query results and there are a lot of duplicated lines. i can post my query if it would be helpful. i'm using some select case there..
EDIT:
THANK YOU guys but i solved that by copying the results of the main query to input of another one and adding distinct and sum clauses
SELECT description, MAX(number1) AS number1, MAX(number2) AS number2)
FROM myTable
GROUP BY description
At last in Oracle, you can use "When"
Eg:
SELECT
DESCRIPTION,
CASE WHEN SUMPRICE1 IS NULL THEN
CASE WHEN SUMPRICE2 IS NULL THEN
CASE WHEN SUMPRICE3 IS NULL THEN
0
ELSE SUMPRICE3 END
ELSE SUMPRICE2 END
ELSE SUMPRICE1 END AS SUMPRICE
FROM MY_TABLE
GROUP BY DESCRIPTION, SUMPRICE
Off course this is useble just if you have a static number of columns.
EDIT: I think I don't get the problem, but, if you don't want to merge the columns, you can use:
SELECT DESCRIPTION,
MAX(SUMPRICE1) AS SUMPRICE1,
MAX(SUMPRICE2) AS SUMPRICE2,
MAX(SUMPRICEN) AS SUMPRICEN
FROM MY_TABLE
GROUP BY DESCRIPTION
Or you can use the case to avoid the null, in the case of any of rows don't have a value:
SELECT DESCRIPTION,
CASE WHEN MAX(SUMPRICE1) IS NULL THEN 0 ELSE WHEN MAX(SUMPRICE1) END AS SUMPRICE1,
CASE WHEN MAX(SUMPRICE2) IS NULL THEN 0 ELSE WHEN MAX(SUMPRICE2) END AS SUMPRICE2,
CASE WHEN MAX(SUMPRICEN) IS NULL THEN 0 ELSE WHEN MAX(SUMPRICEN) END AS SUMPRICEN
FROM MY_TABLE
GROUP BY DESCRIPTION

SQL - CountIf on a column

Trying to do some calculations via SQL on my iSeries and have the following conundrum: I need to count the number of times a certain value appears in a column. My select statement is as follows:
Select
MOTRAN.ORDNO, MOTRAN.OPSEQ, MOROUT.WKCTR, MOTRAN.TDATE,
MOTRAN.LBTIM, MOROUT.SRLHU, MOROUT.RLHTD, MOROUT.ACODT,
MOROUT.SCODT, MOROUT.ASTDT, MOMAST.SSTDT, MOMAST.FITWH,
MOMAST.FITEM,
CONCAT(MOTRAN.ORDNO, MOTRAN.OPSEQ) As CON,
count (Concat(MOTRAN.ORDNO, MOTRAN.OPSEQ) )As CountIF,
MOROUT.SRLHU / (count (Concat(MOTRAN.ORDNO, MOTRAN.OPSEQ))) as calc
*(snip)*
With this information, I'm trying to count the number of times a value in CON appears. I will need this to do some math with so it's kinda important. My count statement doesn't work properly as it reports a certain value as occurring once when I see it appears 8 times.
Try putting a CASE statement inside a SUM().
SUM(CASE WHEN value = 'something' THEN 1 ELSE 0 END)
This will count the number of rows where value = 'something'.
Similary...
SUM(CASE WHEN t1.val = CONCAT(t2.val, t3.val) THEN 1 ELSE 0 END)
If you're on a supported version of the OS, ie 6.1 or higher...
You might be able to make use of "grouping set" functionality. Particularly the ROLLUP clause.
I can't say for sure without more understanding of your data.
Otherwise, you're going to need to so something like
wth Cnt as (select ORDNO, OPSEQ, count(*) as NbrOccur
from MOTRAN
group by ORDNO, OPSEQ
)
Select
MOTRAN.ORDNO, MOTRAN.OPSEQ, MOROUT.WKCTR, MOTRAN.TDATE,
MOTRAN.LBTIM, MOROUT.SRLHU, MOROUT.RLHTD, MOROUT.ACODT,
MOROUT.SCODT, MOROUT.ASTDT, MOMAST.SSTDT, MOMAST.FITWH,
MOMAST.FITEM,
CONCAT(MOTRAN.ORDNO, MOTRAN.OPSEQ) As CON,
Cnt.NbrOccur,
MOROUT.SRLHU / Cnt.NbrOccur as calc
from
motran join Cnt on mortran.ordno = cnt.ordno and mortran.opseq = cnt.opseq
*(snip)*

multiple count(distinct)

I get an error unless I remove one of the count(distinct ...). Can someone tell me why and how to fix it?
I'm in vfp. iif([condition],[if true],[else]) is equivalent to case when
SELECT * FROM dpgift where !nocalc AND rectype = "G" AND sol = "EM112" INTO CURSOR cGift
SELECT
list_code,
count(distinct iif(language != 'F' AND renew = '0' AND type = 'IN',donor,0)) as d_Count_E_New_Indiv,
count(distinct iif(language = 'F' AND renew = '0' AND type = 'IN',donor,0)) as d_Count_F_New_Indiv /*it works if i remove this*/
FROM cGift gift
LEFT JOIN
(select didnumb, language, type from dp) d
on cast(gift.donor as i) = cast(d.didnumb as i)
GROUP BY list_code
ORDER by list_code
edit:
apparently, you can't use multiple distinct commands on the same level. Any way around this?
VFP does NOT support two "DISTINCT" clauses in the same query... PERIOD... I've even tested on a simple table of my own, DIRECTLY from within VFP such as
select count( distinct Col1 ) as Cnt1, count( distinct col2 ) as Cnt2 from MyTable
causes a crash. I don't know why you are trying to do DISTINCT as you are just testing a condition... I more accurately appears you just want a COUNT of entries per each category of criteria instead of actually DISTINCT
Because you are not "alias.field" referencing your columns in your query, I don't know which column is the basis of what. However, to help handle your DISTINCT, and it appears you are running from WITHIN a VFP app as you are using the "INTO CURSOR" clause (which would not be associated with any OleDB .net development), I would pre-query and group those criteria, something like...
select list_code,
donor,
max( iif( language != 'F' and renew = '0' and type = 'IN', 1, 0 )) as EQualified,
max( iif( language = 'F' and renew = '0' and type = 'IN', 1, 0 )) as FQualified
from
list_code
group by
list_code,
donor
into
cursor cGroupedByDonor
so the above will ONLY get a count of 1 per donor per list code, no matter how many records that qualify. In addition, if one record as an "F" and another does NOT, then you'll have a value of 1 in EACH of the columns... Then you can do something like...
select
list_code,
sum( EQualified ) as DistEQualified,
sum( FQualified ) as DistFQualified
from
cGroupedByDonor
group by
list_code
into
cursor cDistinctByListCode
then run from that...
You can try using either another derived table or two to do the calculations you need, or using projections (queries in the field list). Without seeing the schema, it's hard to know which one will work for you.