Modifying fields with multiIf - clickhouse

I'm trying to modify some shortened data to their full forms. For that I'm using the below query.
WITH (SELECT DISTINCT platform FROM myTable) AS platform1
SELECT
multiIf(platform1 = "A", "ANDROID",
platform1 = "W", "WINDOWS",
platform1 = "I", "iOS"
) AS platform2
But clikhouse is throwing an error:
DB::Exception: Scalar subquery returned more than one row.
How to go about this?

Try this query:
SELECT multiIf(
platform1 = 'A', 'ANDROID',
platform1 = 'W', 'WINDOWS',
platform1 = 'I', 'iOS',
'Unknown') AS platform2
FROM (SELECT DISTINCT platform FROM myTable)
or
SELECT CASE platform1
WHEN 'A' THEN 'ANDROID'
WHEN 'W' THEN 'WINDOWS'
WHEN 'I' THEN 'iOS'
ELSE 'Unknown'
END AS platform2
FROM (SELECT DISTINCT platform FROM myTable)

Related

how to make into an array and also count

I have this data:
app
asscs
mod_asscs
a
56
cb-56
a
67
cb-67
b
38
cb-38
a
12
12
I want to group by column 'app' and count the cases where 'mod_asscs' value is equal to concat('cb-', asscs). I also want to output the array in a separate column 'mod_asscs_array' so that the output is the following:
app
mod_asscs_array
scs_count
a
cb-56, cb-67
2
b
cb-38
1
So far this is what I have:
SELECT DISTINCT
app,
( CASE WHEN concat('cb-', asscs) = mod_asscs THEN mod_asscs || ',') AS mod_asscs_array,
COUNT( CASE WHEN concat('cb-', asscs) = mod_asscs THEN mod_asscs || ',') AS scs_count
FROM data_table
GROUP BY
app
Looks like aggregation.
Sample data:
SQL> with test (app, asscs, mod_asscs) as
2 (select 'a', 56, 'cb-56' from dual union all
3 select 'a', 67, 'cb-67' from dual union all
4 select 'b', 38, 'cb-38' from dual union all
5 select 'a', 12, '12' from dual
6 )
Query:
7 select app,
8 listagg(mod_asscs, ', ') within group (order by mod_asscs) array,
9 count(*) cnt
10 from test
11 where mod_asscs = 'cb-'|| asscs
12 group by app;
A ARRAY CNT
- -------------------- ----------
a cb-56, cb-67 2
b cb-38 1
SQL>
If you need to show all the "apps", even those with a "count" of zero, then you need conditional aggregation, something like this:
with
test (app, asscs, mod_asscs) as (
select 'a', 56, 'cb-56' from dual union all
select 'a', 67, 'cb-67' from dual union all
select 'b', 38, 'cb-38' from dual union all
select 'a', 12, '12' from dual union all
select 'c', 33, 'cb-23' from dual
)
select app,
listagg(case when mod_asscs = 'cb-' || asscs
then mod_asscs end, ', ')
within group (order by asscs) as mod_asscs_array,
count(case when mod_asscs = 'cb-' || asscs
then mod_asscs end) as scs_count
from test
group by app
order by app -- if needed
;
APP MOD_ASSCS_ARRAY SCS_COUNT
--- -------------------- ----------
a cb-56, cb-67 2
b cb-38 1
c 0
if there are duplicates in the array, do I do listagg(distinct.. and count(distinct case when ...?
You cannot use LISTAGG(DISTINCT ... as the LISTAGG function does not currently support the DISTINCT keyword; instead you need to use DISTINCT first in a sub-query and then use LISTAGG:
SELECT app,
LISTAGG(mod_asscs, ',') WITHIN GROUP (ORDER BY mod_asscs)
AS mod_asscs_array,
COUNT(*) AS scs_count
FROM (
SELECT DISTINCT
app,
mod_asscs
FROM data_table
WHERE 'cb-' || asscs = mod_asscs
)
GROUP BY app
Which, for the sample data:
CREATE TABLE data_table (app, asscs, mod_asscs) AS
SELECT 'a', 56, 'cb-56' FROM DUAL UNION ALL
SELECT 'a', 56, 'cb-56' FROM DUAL UNION ALL
SELECT 'a', 67, 'cb-67' FROM DUAL UNION ALL
SELECT 'b', 38, 'cb-38' FROM DUAL UNION ALL
SELECT 'a', 12, '12' FROM DUAL;
Outputs:
APP
MOD_ASSCS_ARRAY
SCS_COUNT
a
cb-56,cb-67
2
b
cb-38
1
db<>fiddle here

SQL Select related tables into new columns

I have a table in SQL that has 3 columns:
CategoryName
WarnInterval
ErrorInterval
And then I have another table which has 4 columns:
CategoryName
GroupName
IncludedExcluded
Match
Each row in this table has 2 unique records based on CategoryName, GroupName and IncludedExcluded. For example, as json it looks like this:
{
categoryName: 'Folders',
groupName: 'Products',
includeExcluded: 'E',
match: 'SomeProduct'
}, {
categoryName: 'Folders',
groupName: 'Products',
includeExcluded: 'I',
match: 'SomeOtherProduct'
}
There are 3 Groups (Products, Reps and BusinessCategories), so each Category has only 6 rows of data in this table.
I want to generate an SQL statement that pulls the tables into columns that I can then parse into a json object like this:
{
categoryName: 'Folders',
warnInterval: 40,
errorInterval: 60,
groups: [{
groupName: 'Products',
Include: 'SomeProduct',
Exclude: 'SomeOtherProduct'
}, {
groupName: 'Reps',
Include: 'SomeRep',
Exclude: 'SomeOtherRep'
}, {
groupName: 'BusinessCategories',
Include: 'SomeCategory',
Exclude: 'SomeOtherCategory'
}]
}
I would like the SQL statement to join the 2 tables and present the data into columns like this:
CategoryName
WarnInterval
ErrorInterval
ProductTitle (this is the group name)
ProductIncludes (If the IncludedExcluded value is 'I' then put the match in this column)
ProductExcludes (If the IncludedExcluded value is 'E' then put the match in this column)
RepresentativeTitle
RepresentativeIncludes
RepresentativeExcludes
BusinessCategoryTitle
BusinessCategoryIncludes
BusinessCategoryExcludes
I really hope I explained that well. Can someone help me with the SQL for this? PS, it is Oracle :)
Maybe this is what you're after. The query really breaks the category_matches table into a set of six datasets - three groups * two include / exclude flags.
The list of columns in your question includes "ProductTitle (this is the group name)" which doesn't make sense since each of the groups is represented in each row of data. But maybe I have misunderstood
WITH
category_intervals (category_name, warn_interval, error_interval) AS
(SELECT 'Folders',40,60 FROM dual UNION ALL
SELECT 'catA',10,20 FROM dual UNION ALL
SELECT 'catB',50,100 FROM dual
)
,category_matches(category_name, group_name, include_exclude, match_name) AS
(SELECT 'Folders','Products','E','Product 1' FROM dual UNION ALL
SELECT 'Folders','Products','I','Product 2' FROM dual UNION ALL
SELECT 'Folders','Reps','E','Rep 1' FROM dual UNION ALL
SELECT 'Folders','Reps','I','Rep 2' FROM dual UNION ALL
SELECT 'Folders','Business Categories','E','Category 1' FROM dual UNION ALL
SELECT 'Folders','Business Categories','I','Category 2' FROM dual UNION ALL
--
SELECT 'catA','Products','E','Product 3' FROM dual UNION ALL
SELECT 'catA','Products','I','Product 4' FROM dual UNION ALL
SELECT 'catA','Reps','E','Rep 3' FROM dual UNION ALL
SELECT 'catA','Reps','I','Rep 4' FROM dual UNION ALL
SELECT 'catA','Business Categories','E','Category 3' FROM dual UNION ALL
SELECT 'catA','Business Categories','I','Category 4' FROM dual UNION ALL
--
SELECT 'catB','Products','E','Product 5' FROM dual UNION ALL
SELECT 'catB','Products','I','Product 6' FROM dual UNION ALL
SELECT 'catB','Reps','E','Rep 5' FROM dual UNION ALL
SELECT 'catB','Reps','I','Rep 6' FROM dual UNION ALL
SELECT 'catB','Business Categories','E','Category 5' FROM dual UNION ALL
SELECT 'catB','Business Categories','I','Category 6' FROM dual
)
SELECT
ci.category_name
,ci.warn_interval
,ci.error_interval
,ip.match_name product_include
,ep.match_name product_exclude
,ir.match_name rep_include
,er.match_name rep_exclude
,ibc.match_name bus_cat_include
,ibc.match_name bus_catt_exclude
FROM
category_intervals ci
,(SELECT *
FROM category_matches
WHERE group_name = 'Products'
AND include_exclude = 'I'
) ip
,(SELECT *
FROM category_matches
WHERE group_name = 'Products'
AND include_exclude = 'E'
) ep
,(SELECT *
FROM category_matches
WHERE group_name = 'Reps'
AND include_exclude = 'I'
) ir
,(SELECT *
FROM category_matches
WHERE group_name = 'Reps'
AND include_exclude = 'E'
) er
,(SELECT *
FROM category_matches
WHERE group_name = 'Business Categories'
AND include_exclude = 'I'
) ibc
,(SELECT *
FROM category_matches
WHERE group_name = 'Business Categories'
AND include_exclude = 'E'
) ebc
WHERE 1=1
AND ci.category_name = ip.category_name
AND ci.category_name = ep.category_name
AND ci.category_name = ir.category_name
AND ci.category_name = er.category_name
AND ci.category_name = ibc.category_name
AND ci.category_name = ebc.category_name
ORDER BY
ci.category_name
;

ORA-32033: unsupported column aliasing

I have a query that is working on oracle 12c but not in 10g. I am not sure what the problem is:
My query is:
WITH tab1(rn,begin_chq_num,chq_lvs_stat,chq_num_of_lvs,tes) AS
(SELECT 1 rn,
begin_chq_num,
chq_lvs_stat,
chq_num_of_lvs,
SUBSTR(chq_lvs_stat,1,1) tes
FROM tbaadm.chq_book_table
WHERE del_flg != 'Y'
AND acid IN
(SELECT acid
FROM tbaadm.GENERAL_ACCT_MAST_TABLE
WHERE foracid = '01411110171546'
)
UNION ALL
SELECT rn + 1 rn,
begin_chq_num,
chq_lvs_stat,
chq_num_of_lvs,
SUBSTR(chq_lvs_stat,rn + 1,1) tes
FROM tab1
WHERE rn < chq_num_of_lvs
)
SELECT
CASE
WHEN begin_chq_num = 1
THEN rn
ELSE begin_chq_num +(rn-1)
END cheque_num,
begin_chq_num
||'-'
||(chq_num_of_lvs+begin_chq_num-1) cheque_range,
DECODE(tes, 'I', 'Issued', 'P', 'Cleared', 'U', 'Unused', 'S', 'Stopped', 'C', 'Cautioned', 'D', 'Destroyed', 'R', 'Returned Paid', 'T', 'Transfered') status
FROM tab1
ORDER BY chq_lvs_stat,
rn;
The error is :
ORA-32033: unsupported column aliasing
32033. 00000 - "unsupported column aliasing"
*Cause: column aliasing in WITH clause is not supported yet
*Action: specify aliasing in defintion subquery and retry
What should I do different?
In Oracle 10g, the sub-query factoring clause does not support column aliases or recursive sub-queries. The syntax you are using appears in 11gR2.
You need to change:
WITH tab1(rn,begin_chq_num,chq_lvs_stat,chq_num_of_lvs,tes) AS
To:
WITH tab1 AS
And find a different solution that does not use a recursive subquery factoring clause.
I think you could do this in Oracle 10g:
WITH tab1 AS (
SELECT l.COLUMN_VALUE rn,
begin_chq_num,
chq_lvs_stat,
chq_num_of_lvs,
SUBSTR(chq_lvs_stat,l.COLUMN_VALUE,1) tes
FROM tbaadm.chq_book_table t,
TABLE(
CAST(
MULTISET(
SELECT LEVEL
FROM DUAL
CONNECT BY LEVEL <= LENGTH( t.chq_lvs_stat )
)
AS SYS.ODCINUMBERLIST
)
) l
WHERE del_flg != 'Y'
AND acid IN ( SELECT acid
FROM tbaadm.GENERAL_ACCT_MAST_TABLE
WHERE foracid = '01411110171546'
)
)
SELECT CASE
WHEN begin_chq_num = 1
THEN rn
ELSE begin_chq_num +(rn-1)
END cheque_num,
begin_chq_num
||'-'
||(chq_num_of_lvs+begin_chq_num-1) cheque_range,
DECODE(
tes,
'I', 'Issued',
'P', 'Cleared',
'U', 'Unused',
'S', 'Stopped',
'C', 'Cautioned',
'D', 'Destroyed',
'R', 'Returned Paid',
'T', 'Transfered'
) status
FROM tab1
ORDER BY chq_lvs_stat, rn;

Oracle pivot query results in a "command not properly ended" error

When firing the following query to a 10g Oracle database:
SELECT * FROM (
SELECT T1.ID, T2.ACCT_NO, ROW_NUMBER() OVER (PARTITION BY T1.ID ORDER BY T1.ID DESC) AS RRRRRRR
FROM TABLE1 T1
INNER JOIN TABLE T2 ON T1.ID = T2.ID
WHERE T1.ID = 666
)
PIVOT (MIN(T1.ID) AS ALIAS1 FOR RRRRRRR IN (1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
I get an "command not properly ended" error.
I've searched for Oracle pivot examples and they all pretty much showed the same example.
What am I missing here?
As #APC pointed out there is no PIVOT function in oracle 10g, so you can use an aggregate function and a CASE, similar to this:
SELECT id, acct_no,
min(case when RRRRRRR = 1 then id end) as '1',
min(case when RRRRRRR = 2 then id end) as '2',
min(case when RRRRRRR = 3 then id end) as '3',
min(case when RRRRRRR = 4 then id end) as '4',
min(case when RRRRRRR = 5 then id end) as '5',
min(case when RRRRRRR = 6 then id end) as '6',
min(case when RRRRRRR = 7 then id end) as '7',
min(case when RRRRRRR = 8 then id end) as '8',
min(case when RRRRRRR = 9 then id end) as '9',
min(case when RRRRRRR = 10 then id end) as '10'
FROM
(
SELECT T1.ID, T2.ACCT_NO, ROW_NUMBER() OVER (PARTITION BY T1.ID ORDER BY T1.ID DESC) AS RRRRRRR
FROM TABLE1 T1
INNER JOIN TABLE T2 ON T1.ID = T2.ID
WHERE T1.ID = 666
) x
GROUP BY id, acct_no
Your syntax is impeccable. Unfortunately PIVOT was introduced in Oracle 11g and you're using 10g.

Multiple select for aleady joined table

Below is a part of my select query. In the same query I am selecting COLUMN_1 from a table TABLE2 with condition check. Also I am joining this table at end with one of the condition in the inner select as below. Can we have any other way to handle this situation with out using multiple `SELECT inside.
SELECT
T1.COLUMN_1
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='A' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_2
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='B' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_3
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='C' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_4
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='D' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_5
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='E' AND COLUMN_11=T2.COLUMN_11)
, T1.COLUMN_6
, (SELECT COLUMN_1 FROM TABLE2 WHERE COLUMN_22 ='F' AND COLUMN_11=T2.COLUMN_11)
FROM TABLE1 T1, TABLE2 T2
-- plus two more tables
--plus some other conditions
WHERE T1.COLUMN_11=T2.COLUMN_11
Use CASE instead:
SELECT T1.COLUMN_1
,CASE
WHEN T2.COLUMN_22 = 'A'
THEN T2.COLUMN_1
END
,T1.COLUMN_2
,CASE
WHEN T2.COLUMN_22 = 'B'
THEN T2.COLUMN_1
END
,T1.COLUMN_3
,CASE
WHEN T2.COLUMN_22 = 'C'
THEN T2.COLUMN_1
END
,T1.COLUMN_4
,CASE
WHEN T2.COLUMN_22 = 'D'
THEN T2.COLUMN_1
END
,T1.COLUMN_5
,CASE
WHEN T2.COLUMN_22 = 'E'
THEN T2.COLUMN_1
END
,T1.COLUMN_6
,CASE
WHEN T2.COLUMN_22 = 'F'
THEN T2.COLUMN_1
END
FROM TABLE1 T1
INNER JOIN TABLE2 T2 ON T1.COLUMN_11 = T2.COLUMN_11;
EDIT
I changed the query to use the ansi join syntax. But that change is irrelevant to what you are asking. You can keep your join syntax if you want. The only relevant change is in the SELECT portion of the query.
You won't have very clean solutions I think. Another possibility is with an inner join by case:
SELECT
T1.COLUMN_1,
T2_1.COLUMN_1,
T1.COLUMN_2,
T2_2.COLUMN_1
T1.COLUMN_3,
T2_3.COLUMN_1
T1.COLUMN_4,
T2_4.COLUMN_1
T1.COLUMN_5,
T2_5.COLUMN_1
T1.COLUMN_6,
T2_6.COLUMN_1
FROM TABLE1 T1
INNER JOIN TABLE2 T2_1 ON T1.COLUMN_11=T2_1.COLUMN_11 AND T2_1.COLUMN_22 = 'A',
INNER JOIN TABLE2 T2_2 ON T1.COLUMN_11=T2_2.COLUMN_11 AND T2_2.COLUMN_22 = 'B',
INNER JOIN TABLE2 T2_3 ON T1.COLUMN_11=T2_3.COLUMN_11 AND T2_3.COLUMN_22 = 'C',
INNER JOIN TABLE2 T2_4 ON T1.COLUMN_11=T2_4.COLUMN_11 AND T2_4.COLUMN_22 = 'D',
INNER JOIN TABLE2 T2_5 ON T1.COLUMN_11=T2_5.COLUMN_11 AND T2_5.COLUMN_22 = 'E',
INNER JOIN TABLE2 T2_6 ON T1.COLUMN_11=T2_6.COLUMN_11 AND T2_6.COLUMN_22 = 'F',
WHERE
etc...

Resources