Trim first 3 characters in DB2 - db2

How to trim first three characters of a column in select query in DB2?. I tried below query but did not work
SELECT
MIN(Column1),UPPER(RIGHT(Column2, LENGTH(Column2 - 3))) AS TEST
FROM TEST_TABLE
GROUP BY UPPER(Column2)
ORDER BY UPPER(Column2);
I got below exception
The statement cannot be processed.
User response:
Correct the statement by including the expression in the GROUP BY clause
that are in the SELECT clause, HAVING clause, or ORDER BY clause or by
removing the column function from the SELECT statement.
sqlcode: -119
sqlstate: 42803

You can simply use substring function to do the same.
SELECT
MIN(Column1),substr(Column2,4) AS TEST
FROM TEST_TABLE
GROUP BY UPPER(substr(Column2,4))
ORDER BY UPPER(substr(Column2,4));

Just do:
SELECT
MIN(Column1),UPPER(substr(Column2, 4)) AS TEST
FROM TEST_TABLE
GROUP BY UPPER(substr(Column2, 4))
ORDER BY 2;

Related

Unable to get row number - subquery in FROM must have an alias [duplicate]

I have this query I have written in PostgreSQL that returns an error saying:
[Err] ERROR:
LINE 3: FROM (SELECT DISTINCT (identifiant) AS made_only_recharge
This is the whole query:
SELECT COUNT (made_only_recharge) AS made_only_recharge
FROM (
SELECT DISTINCT (identifiant) AS made_only_recharge
FROM cdr_data
WHERE CALLEDNUMBER = '0130'
EXCEPT
SELECT DISTINCT (identifiant) AS made_only_recharge
FROM cdr_data
WHERE CALLEDNUMBER != '0130'
)
I have a similar query in Oracle that works fine. The only change is where I have EXCEPT in Oracle I have replaced it with the MINUS key word. I am new to Postgres and don't know what it is asking for. What's the correct way of handling this?
Add an ALIAS onto the subquery,
SELECT COUNT(made_only_recharge) AS made_only_recharge
FROM
(
SELECT DISTINCT (identifiant) AS made_only_recharge
FROM cdr_data
WHERE CALLEDNUMBER = '0130'
EXCEPT
SELECT DISTINCT (identifiant) AS made_only_recharge
FROM cdr_data
WHERE CALLEDNUMBER != '0130'
) AS derivedTable -- <<== HERE
In the case of nested tables, some DBMS require to use an alias like MySQL and Oracle but others do not have such a strict requirement, but still allow to add them to substitute the result of the inner query.

PostgreSQL query with unnest returns no result row for null values

I am trying to query the values that divides comma separated values in a column as different records ,I could not get the values if the column has null values, Below is the example
Table name: test
id,name,list
1,a, a1,b1
2,b, null
3,c,c1
Query which is used
select id,name,unnest(string_to_array(list,',')) from test;
Result:
1,a,a1
1,a,b1
3,c,c1
But I need to consider the null values and return the result as below ,I tried using coalesce but that did not work, kindly help me out with the solution
Expected result:
1,a,a1
1,a,b1
2,b,null
3,c,c1
Use unnest() with an outer join:
select t.id, t.name, u.element
from test t
left join unnest(string_to_array(t.list,',')) on true
order by t.id;

How to get ids of grouped by rows in postgresql and use result?

I have a table containing transactions with an amount. I want to create a batch of transactions so that the sum of amount of each 'group by' is negative.
My problematic is to get all ids of the rows concerned by a 'group by' where each group is validate by a sum condition.
I find many solutions which don't work for me.
The best solution I found is to request the db a first time with the 'group by' and the sum, then return ids to finally request the db another time with all of them.
Here an example of what I would like (it doesn't work!) :
SELECT * FROM transaction_table transaction
AND transaction.id IN (
select string_agg(grouped::character varying, ',' ) from (
SELECT array_agg(transaction2.id) as grouped FROM transaction_table transaction2
WHERE transaction2.c_scte='c'
AND (same conditions)
GROUP BY
transaction2.motto ,
transaction2.accountBnf ,
transaction2.payment ,
transaction2.accountClt
HAVING sum(transaction2.amount)<0
)
);
the result of the array_agg is like:
{39758,39759}
{39757,39756,39755,39743,39727,39713}
and the string_agg is :
{39758,39759},{39757,39756,39755,39743,39727,39713}
Now I just need to use them but I don't know how to...
unfortunatly, it doesn't work because of type casting :
ERROR: operator does not exist: integer = integer[]
IndiceĀ : No operator matches the given name and argument type(s). You might need to add explicit type casts.
Maybe you are looking for
SELECT id, motto, accountbnf, payment, accountclnt, amount
FROM (SELECT id, motto, accountbnf, payment, accountclnt, amount,
sum(amount)
OVER (PARTITION BY motto, accountbnf, payment, accountclnt)
AS group_total
FROM transaction_table) AS q
WHERE group_total < 0;
The inner SELECT adds an additional column using a window function that calculates the sum for each group, and the outer query removes all results where that sum is not negative.
Finally I found this option using the 'unnest' method. It works perfectly.
Array_agg bring together all ids in different array
unnest flattened all of them
This comes from here
SELECT * FROM transaction_table transaction
WHERE transaction.id = ANY(
SELECT unnest(array_agg(transaction2.id)) as grouped FROM transaction_table transaction2
WHERE transaction2.c_scte='c'
AND (same conditions)
GROUP BY
transaction2.motto ,
transaction2.accountBnf ,
transaction2.payment ,
transaction2.accountClt
HAVING sum(transaction2.amount)<0
);
The problem with this solution is that hibernate doesn't take into account the array_agg method.

Can't understand why using CAST errors out but using CONVERT does not?

The following code that executes without any issue:
Select
#ICDCodes.ICD_Code,
#ICDCodes.Description,
Count(#DiseaseIndex.VstIntID) AS 'Total Count',
Sum(DATEDIFF(dd,#DiseaseIndex.AdmitDtSrt,#DiseaseIndex.DschrgDtTm )) as 'Total LOS',
ISNULL(AVG(CONVERT(NUMERIC(8,2),DATEDIFF(DAY,#DiseaseIndex.AdmitDtSrt,#DiseaseIndex.DschrgDtTm))),0) as 'Total Avg LOS'
FROM #DiseaseIndex LEFT JOIN #ICDCodes on #DiseaseIndex.VstIntID = #ICDCodes.VstIntID
WHERE ICD_Type IN ('P','S')
GROUP BY #ICDCodes.ICD_Code, #ICDCodes.Descriptio
but this code throws an error:
SELECT
#ICDCodes.ICD_Code,
#ICDCodes.Description,
Count(#DiseaseIndex.VstIntID) AS 'Total Count',
Sum(CAST(DATEDIFF(dd,#DiseaseIndex.AdmitDtSrt,#DiseaseIndex.DschrgDtTm )AS NUMERIC(8,2))) AS 'Total LOS',
ISNULL(CAST(DATEDIFF(DAY,#DiseaseIndex.AdmitDtSrt,#DiseaseIndex.DschrgDtTm) AS NUMERIC(8,2)),0) as 'Total Avg LOS'
FROM #DiseaseIndex LEFT JOIN #ICDCodes on #DiseaseIndex.VstIntID = #ICDCodes.VstIntID
WHERE ICD_Type IN ('P','S')
GROUP BY #ICDCodes.ICD_Code, #ICDCodes.Description`
This is the Error it generates:
Msg 8120, Level 16, State 1, Line 191
Column '#DiseaseIndex.AdmitDtSrt' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Msg 8120, Level 16, State 1, Line 191
Column '#DiseaseIndex.DschrgDtTm' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Basically it is the same code with the exception that one set uses CAST() and the other one uses CONVERT().
Can someone explain why the CAST requires adding the dates to the GROUP BY statement while the CONVERT does not?
Thanks in advance
Update
In the second query you've forgot the AVG:
first query:
ISNULL(AVG(CONVERT(NUMERIC(8,2),DATEDIFF(DAY,#DiseaseIndex.AdmitDtSrt,#DiseaseIndex.DschrgDtTm))),0) as 'Total Avg LOS
second query:
ISNULL(CAST(DATEDIFF(DAY,#DiseaseIndex.AdmitDtSrt,#DiseaseIndex.DschrgDtTm) AS NUMERIC(8,2)),0) as 'Total Avg LOS'
First version:
(This was correct for the first version of the question.)
This is because you use NUMERIC(8,2) in the convert, but DECIMAL(8,2) in the cast.
Though numeric and decimal are documented to be interchangeable synonyms, having a numeric in he group by clause and a decimal in the select clause will raise that error.
Here is a simple demo:
DECLARE #T AS TABLE
(
col1 int,
col2 int
)
INSERT INTO #T VALUES
(1,1),(2,1),(3,1),
(4,2),(5,2),(6,2),
(7,3)
SELECT CAST(Col2 as NUMERIC(8,2)),
AVG(Col1)
FROM #T
GROUP BY CONVERT(DECIMAL(8,2), Col2)
Results:
Column '#T.col2' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
However, if you change the select to decimal or the group by to numeric, the error message is gone and the select returns the result set:
SELECT CAST(Col2 as DECIMAL(8,2)),
AVG(Col1)
FROM #T
GROUP BY CONVERT(DECIMAL(8,2), Col2)
Results:
1.00 2
2.00 5
3.00 7
See a live demo on rextester

SQL Server 2008 R2 String concat using CASE..WHEN in the ORDER BY clause

I have a strange behavior when using a CASE..WHEN in an ORDER BY clause. Here it is :
create table #test(num int,val nvarchar(30))
insert into #test select 1,'VAL1'
insert into #test select 2,'VAL2'
insert into #test select 3,'VAL3'
insert into #test select 4,'VAL4'
declare #TmpLib nvarchar(max)
select #TmpLib=''
SELECT #TmpLib = #TmpLib+ t.val
FROM #test t
ORDER BY t.num
select #TmpLib
In this case my result is VAL1VAL2VAL3VAL4
But if I change the ORDER BY clause like this
ORDER BY CASE WHEN t.num=1 THEN 0 WHEN t.num=2 THEN 98 WHEN t.num>=3 AND t.num<4 THEN 99 ELSE 1 END, t.num
Then the result is VAL3.
I don't understand how an ORDER BY clause may affect the concatenation like this. I would expect to have still all my values sorted in my #TmLib variable, no ?
Of course I could first select my records in a second table to sort them and then do my concatenation but I would prefer to do it once !
Thanks.