Refactoring from WM_CONCAT to LISTAGG function - oracle11g

The oracle version has been updated and WM_CONCAT function stopped working.
I have to changed it for LISTAGG function but it takes only 2 arguments LISTAGG(measure_expr, delimiter)
What if there are two columns: WM_CONCAT(COB.COD_COB||':'||COB_1.NOM_COB) ?
I tried:
LISTAGG((COB.COD_COB||':'||COB_1.NOM_COB), ':') WITHIN GROUP (ORDER BY COB.COD_COB,COB_1.NOM_COB) AS COB_DESC
but it gives me an error
SELECT DISTINCT
-- TO_CHAR(WM_CONCAT(COB.COD_COB||':'||COB_1.NOM_COB)) AS COB_DESC,
LISTAGG((COB.COD_COB||':'||COB_1.NOM_COB), ':') WITHIN GROUP (ORDER BY COB.COD_COB,COB_1.NOM_COB) AS COB_DESC
FROM COBERTURAS_REDUCIDA_UW COB
LEFT JOIN A1002150 COB_1 ON COB.COD_CIA = COB_1.COD_CIA
GROUP BY COB.COD_CIA

Related

ORA-00932: inconsistent datatypes: expected DATE got NUMBER

I am using Oracle 11g and running the following query in oracle toad:
WITH
CTEDevices (CREATED_ON, CUSTOMER_INFO_ID, DEVICE_MAKE, DEVICE_Model) AS (
SELECT
Trunc(RD.CREATED_ON),
RD.CUSTOMER_INFO_ID,
RD.DEVICE_MAKE,
RD.DEVICE_Model
FROM Schema.Table1 RD
WHERE RD.PARAM_CHANNEL_ID = 1
AND RD.CREATED_ON >= '01-may-2022'
AND RD.CREATED_ON <= '02-may-2022'
GROUP BY
Trunc(RD.CREATED_ON),
RD.CUSTOMER_INFO_ID,
RD.DEVICE_MAKE,
RD.DEVICE_Model
),
CTERegistration (CREATED_ON, CUSTOMER_INFO_ID, DEVICE_MAKE, DEVICE_Model) AS
(
SELECT
CI.Customer_Info_Id,
Trunc(CI.created_on),
'CI.DEVICE_MAKE',
'CI.DEVICE_Model'
FROM Schema.Table2 CI
Where CI.CUSTOMER_TYPE = 'A'
AND CI.CREATED_ON >= '01-may-2022'
AND CI.CREATED_ON <= '02-may-2022'
)
SELECT
CTEDevices.CREATED_ON, CTEDevices.CUSTOMER_INFO_ID, CTEDevices.DEVICE_MAKE, CTEDevices.DEVICE_Model,
CTERegistration.CREATED_ON, CTERegistration.CUSTOMER_INFO_ID, CTERegistration.DEVICE_MAKE, CTERegistration.DEVICE_Model
FROM CTEDevices INNER JOIN CTERegistration ON (CTEDevices.CUSTOMER_INFO_ID = CTERegistration.CUSTOMER_INFO_ID AND (CTEDevices.CREATED_ON = CTERegistration.CREATED_ON));
Individual qeueries were running successfully but when going to run as combined one getting the following error:
ORA-00932: inconsistent datatypes: expected DATE got NUMBER
Please help.
Thanks
Culprit is the 2nd CTE:
CTERegistration (CREATED_ON, CUSTOMER_INFO_ID, DEVICE_MAKE, DEVICE_Model) AS
( 1st 2nd
SELECT
CI.Customer_Info_Id, 1st
Trunc(CI.created_on), 2nd
'CI.DEVICE_MAKE', ...
The 1st column is supposed to be CREATED_ON (which is, apparently, DATE datatype value), while the 2nd column is then CUSTOMER_INFO_ID. Your query has it just the opposite, so - fix it:
CTERegistration (CREATED_ON, CUSTOMER_INFO_ID, DEVICE_MAKE, DEVICE_Model) AS
(
SELECT
Trunc(CI.created_on),
CI.Customer_Info_Id,
'CI.DEVICE_MAKE', ...
If you wonder why separate queries work, well - no reason why not. Oracle doesn't care how you named columns, but you can't join them any way you want.

Snowflake, Recursive CTE , Getting error String 'AAAA_50>BBBB_47>CCCC_92' is too long and would be truncated in 'CONCAT'

I am creating a recursive CTE in snowflake for getting complete path an getting following error:
String 'AAAA_50>BBBB_47>CCCC_92' is too long and would be truncated in 'CONCAT'
My script is as follows: (it works fine for 2 levels, starts failing for 3rd level)
with recursive plant
(child_col,parent_col,val )
as
(
select child_col, '' parent_col , trim(child_col) from My_view
where condition1 = 'AAA'
union all
select A.child_col,A.parent_col,
concat(trim(A.child_col),'>')||trim(val)
from My_view A
JOIN plant as B ON trim(B.child_col) = trim(A.parent_col)
)
select distinct * from plant
Most likely the child_col data type is defined as VARCHAR (N), this type is being passed on. Because CONCAT Returns:
The data type of the returned value is the same as the data type of
the input value(s).
Try to explicitly cast a type to a string like this cast(trim(child_col) as string):
Full code:
with recursive plant (child_col,parent_col,val )
as (
select child_col, '' parent_col , cast(trim(child_col) as string)
from My_view
where condition1 = 'AAA'
union all
select A.child_col, A.parent_col, concat(trim(A.child_col),'>')||trim(val)
from My_view A
join plant as B ON trim(B.child_col) = trim(A.parent_col)
)
select distinct * from plant
Remember that recursion in Snowflake is limited to 100 loops by default.
If you want to increase them, you need to contact support.
Reference: CONCAT Troubleshooting a Recursive CTE

SELECT queries in a loop

I am working on an sqlite3 shell.
SELECT * FROM tasks WHERE name in ("TaskA", "TaskD") LIMIT 5;
The above statement will print the first 5 rows only. Is there a way to write this statement so the first 5 rows from each of "TaskA" and "TaskD" results are printed?
In essence, I am trying to write a loop akin to:
FOR task in ("TaskA", "TaskD") SELECT * FROM tasks WHERE name = task LIMIT 5;
But I do not know the proper syntax.
Use ROW_NUMBER() window function:
SELECT *
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY name ORDER BY rowid) rn
FROM tasks
WHERE name IN ("TaskA", "TaskD")
)
WHERE rn <= 5
I used the column rowid to define the order of the rows.
If there is another column in your table, like a date column, that can be used to define the order, you can replace rowid with that column.

sort semicolon separated values per row in a column

I want to sort semicolon separated values per row in a column. Eg.
Input:
abc;pqr;def;mno
xyz;pqr;abc
abc
xyz;jkl
Output:
abc;def;mno;pqr
abc;pqr;xyz
abc
jkl;xyz
Can anyone help?
Perhaps something like this. Breaking it down:
First we need to break up the strings into their component tokens, and then reassemble them, using LISTAGG(), while ordering them alphabetically.
There are many ways to break up a symbol-separated string. Here I demonstrate the use of a hierarchical query. It requires that the input strings be uniquely distinguished from each other. Since the exact same semicolon-separated string may appear more than once, and since there is no info from the OP about any other unique column in the table, I create a unique identifier (using ROW_NUMBER()) in the most deeply nested subquery. Then I run the hierarchical query to break up the inputs and then reassemble them in the outermost SELECT.
with
test_data as (
select 'abc;pqr;def;mno' as str from dual union all
select 'xyz;pqr;abc' from dual union all
select 'abc' from dual union all
select 'xyz;jkl' from dual
)
-- End of test data (not part of the solution!)
-- SQL query begins BELOW THIS LINE.
select str,
listagg(token, ';') within group (order by token) as sorted_str
from (
select rn, str,
regexp_substr(str, '([^;]*)(;|$)', 1, level, null, 1) as token
from (
select str, row_number() over (order by null) as rn
from test_data
)
connect by level <= length(str) - length(replace(str, ';')) + 1
and prior rn = rn
and prior sys_guid() is not null
)
group by rn, str
;
STR SORTED_STR
--------------- ---------------
abc;pqr;def;mno abc;def;mno;pqr
xyz;pqr;abc abc;pqr;xyz
abc abc
xyz;jkl jkl;xyz
4 rows selected.

Get a count of rows that meet condition

SQLITE3
Task: get a data set that contains the following data - SEE NOTES BESIDE COLUMNS
SELECT DISTINCT DateTime(Rounded, 'unixepoch') AS RoundedDate, -- Rounded DateTime to the floor hour
Count() AS Count, -- Count of items that registered within the above time
CAST (avg(Speed) AS INT) AS AverageSpeed, -- Average table.Speed column data within the defined datetime
Count() AS SpeederCount -- ?? WTF? [pseudo constraints: if Speed > Speedlimit then +1]
FROM RawSpeedLane AS sl
INNER JOIN
SpeedLaneSearchData AS slsd ON slsd.ParentId = sl.Id
INNER JOIN
Projects AS p ON p.ProjectId = sl.ProjectId
WHERE sl.ProjectId = 72
GROUP BY RoundedDate;
The SQL above is currently gives me all the data I need, EXECPT for the last column.
This last column is supposed to be the count of records where that pass specific criteria. The only way I have found to successfully do this is to build a sub query... Cool? okay, but the problem is the sub query takes 4 minutes to run because well... I suck at SQL :P No matter how many different ways I've tried to write it, it still takes forever.
Here is the long, but working version.
SELECT DISTINCT RoundedDate,
Count() AS Count,
CAST (avg(Speed) AS INT) AS AverageSpeed,
(
SELECT count()
FROM RawSpeedLane AS slr
WHERE slr.ProjectId = 72 AND
datetime( ( (strftime('%s', Start) - (strftime('%M', Start) * 60 + strftime('%S', Start) ) ) ), 'unixepoch') = sl.RoundedDate AND
Speed > p.SpeedLimit
)
AS SpeederCount
FROM SpeedLaneReportDataView AS sl
INNER JOIN
Projects AS p ON p.ProjectId = sl.ProjectId
WHERE sl.ProjectId = 72
GROUP BY RoundedDate;
I currently just tried this for the last column
(select Count() where sl.Speed > p.SpeedLimit)
but as expected, i got 1s and 0s im not really sure on what to do here. Any hints or help that lead me in the right direction is very much appreciated.
I don't think SQLite has an IIF but CASE works.
This is a response to Backs answer, but I can't comment yet.
SELECT DISTINCT DateTime(Rounded, 'unixepoch') AS RoundedDate, -- Rounded DateTime to the floor hour
Count() AS Count, -- Count of items that registered within the above time
CAST (avg(Speed) AS INT) AS AverageSpeed, -- Average table.Speed column data within the defined datetime
SUM(CASE WHEN Speed > SpeedLimit THEN 1 ELSE 0 END) AS SpeederCount
FROM RawSpeedLane AS sl
With SUM and IIF:
SELECT DISTINCT DateTime(Rounded, 'unixepoch') AS RoundedDate, -- Rounded DateTime to the floor hour
Count() AS Count, -- Count of items that registered within the above time
CAST (avg(Speed) AS INT) AS AverageSpeed, -- Average table.Speed column data within the defined datetime
SUM(IIF(Speed > SpeedLimit, 1, 0)) AS SpeederCount
FROM RawSpeedLane AS sl

Resources