Dynamic Pivoting in Oracle - sql

Hi I want to apply dynamic pivoting on table with structure as
ID Type Amount
--- ------ ------
1 AB 50
2 PQR 100
3 AB 60
4 PQR 120
I want result in below format:
In my table, every month Type column's values changing. So I want dynamically pivot table values to get desired result. I was tried by pivoting as per syntax , but whenever I tried to place sub-query in IN operator of pivot, it has given an error. I am using Oracle 10 g.
Can anyone please assist me in this issue. Thanks.
Select * from(
Select ID , Type, Value
from mytable)x
pivot(sum(Value) for Type IN (Select distinct Type from myTable))

If you want to have dynamic results, you may prefer using xml option of pivoting
with t(ID, Type, Amount) as
(
select 1,'AB',50 from dual union all
select 2,'PQR',100 from dual union all
select 3,'AB',60 from dual union all
select 4,'PQR',120 from dual
)
select *
from(
select ID , Type, Amount
from t )
pivot xml(
sum(Amount) as sum_amount for (type)
in (Select distinct Type from t)
);
Rextester Demo

Related

SQL : How to find the count of an particular category values from an column with string values

I have a SQL Table called "category" looks like this
id | category
--------------
1 | 3,2
2 | 1
3 | 4,3,2
4 | 2,1
5 | 1,4
6 | 2,3,4
There are multiple category id's in the column "category", I need to find the count of an particular category values.
Current method I am using is:
select count(distinct(Category)) AS coldatacount from table_name
It gives the count of all the distinct values WHERE as I need to get
the count of all the particular category_id's separately.
if you are trying to get the Category Ids in comma delimited, you can use the string_split function to get distinct category_id
with cte as (
select 1 as id, '3,2' as category union all
select 2, '1' union all
select 3, '4,3,2' union all
select 4, '2,1' union all
select 5, '1,4' union all
select 6, '2,3,4'
)select count(distinct(value)) as category from cte
cross apply string_split(cte.category, ',');
I assumed that #neeraj04 may be looking for count of all Id in the category, continuing with #METAL code:
CREATE TABLE YourTable
(
Id INT IDENTITY,
[Category] VARCHAR(50)
);
INSERT YourTable VALUES ('3,2'), ('1'), ('4,3,2'), ('2,1'), ('1,4'), ('2,3,4');
SELECT CAST(value AS INT) AS category -- Value is string ouptut
, COUNT([value]) AS IdCount
FROM YourTable yt
CROSS APPLY string_split(yt.Category, ',')
GROUP BY [value]
ORDER BY category;
This is a horrible data model. You should not be storing multiple values in a string. You should not be storing numbers as strings.
Sometimes we are stuck with other people's really, really bad decisions. One approach is to split the string and count:
select t.*, cnt
from t cross apply
(select count(*) as cnt
from string_split(t.category) s
) s;
The other is to count commas:
select t.*,
(1 + len(t.category) - len(replace(t.category, ',', '')) as num_elements
Select Count(Value) from (Select Value from Table_Name a Cross Apply
string_split(a.Category, ','))ab Where Value=1

Big Query - String Function

I am very new in BigQuery platform, i want to take the following strings
SOCKETIOEXCEPTION##APS.COM, NULLPOINTEREXCEPTION##RSJAVA.COM, CLASSCASTEEXCEPTION##MPS.COM
And get this as a result: SOCKETIOEXCEPTION, NULLPOINTEREXCEPTION, CLASSCASTEEXCEPTION
Before ## characters I want to separate from a given string and then I want to group by number rows available in the above-mentioned tag like SOCKETIOEXCEPTION, NULLPOINTEREXCEPTION, CLASSCASTEEXCEPTION
Sample db details
How do I write this query?
Below is for BigQuery Standard SQL
#standardSQL
SELECT SPLIT(line, '##')[OFFSET(0)] type, COUNT(1) cnt
FROM `project.dataset.table`
GROUP BY type
You can test, play with above using sample data from your question as in example below
#standardSQL
WITH `project.dataset.table` AS (
SELECT 'SOCKETIOEXCEPTION##111' line UNION ALL
SELECT 'SOCKETIOEXCEPTION##222' UNION ALL
SELECT 'SOCKETIOEXCEPTION##333' UNION ALL
SELECT 'NULLPOINTEREXCEPTION##444' UNION ALL
SELECT 'NULLPOINTEREXCEPTION##555' UNION ALL
SELECT 'CLASSCASTEEXCEPTION##666' UNION ALL
SELECT 'CLASSCASTEEXCEPTION##777' UNION ALL
SELECT 'CLASSCASTEEXCEPTION##888'
)
SELECT SPLIT(line, '##')[OFFSET(0)] type, COUNT(1) cnt
FROM `project.dataset.table`
GROUP BY type
with result
Row type cnt
1 SOCKETIOEXCEPTION 3
2 NULLPOINTEREXCEPTION 2
3 CLASSCASTEEXCEPTION 3

SQL Query to Unpivot dependent column using oracle

i am trying to replicate below scenario using oracle sql query:
i have did it using union query , but in that query i am hitting same table multiple times, is there any alternate for this query?
Please note: col and val are depenedent on each other simillarly col_1 and val_1 are also dependent on each other
select id,col, val from tbl
union
select id,col_1, val_1 from tbl
Oracle 12C+ supports lateral joins, so you can do:
select t.id, v.col, v.val
from tbl t cross join lateral
(select t.col, t.val from dual union all
select t.col_1, t.val from dual
) v;
You can pivot and unpivot multiple columns with the PIVOT and UNPIVOT operators, you just need to know the correct syntax. In your case you want to UNPIVOT. You are losing some information in the way you show the desired output, and perhaps that's OK for your needs; in any case, below I include a column that shows the order of the pairs of columns. (A bit odd, showing 1 for COL/VAL and 2 for COL_1/VAL_1, but I assume those aren't your real column names anyway.) If you don't need the ORD column in the output, just drop it from the SELECT clause.
Note - COLUMN is an Oracle reserved word, it can't be a column name. I changed the column names to C and V in the output.
with
input(id, col, col_1, val, val_1) as (
select 1, 'ABC', 'DEF', 10, 20 from dual union all
select 2, 'GHI', 'JKL', 30, 40 from dual
)
select id, ord, c, v
from input
unpivot ( (c, v) for ord in ((col, val) as 1, (col_1, val_1) as 2))
;
ID ORD C V
---------- ---------- --- ----------
1 1 ABC 10
1 2 DEF 20
2 1 GHI 30
2 2 JKL 40

How to remove duplicate rows in Google BigQuery based on a unique identifier

In SQL, I use the following code to remove duplicates from a table based on a unique ID:
1. SELECT Unique_ID INTO holdkey FROM [Origination] GROUP BY Unique_ID HAVING count(*) > 1
2. SELECT DISTINCT Origination.*
INTO holddups
FROM [Origination], holdkey
WHERE [Origination].Unique_ID = holdkey.Unique_ID
3. DELETE Origination
FROM Origination, holdkey
WHERE Origination.Unique_ID = holdkey.Unique_ID
4. INSERT Origination SELECT * FROM holddups
The second process does not work on BigQuery. Regardless of how I change the query, I get errors for unrecognized columns and tables.
I obviously take out "select into" queries and just set the destination tables manually. I have SQL experience, and I know the process works. Does anyone have a sample of syntax that they use for the process of removing duplicate records based on a unique ID for BQ? Or a way to modify this that would make it run?
So, the trick is in having proper SELECT here
Below example is for BigQuery Standard SQL
#standardSQL
SELECT row[OFFSET(0)].* FROM (
SELECT ARRAY_AGG(t ORDER BY value DESC LIMIT 1) row
FROM `project.dataset.table_with_dups` t
GROUP BY id
)
you can test / play with above using dummy data as below
#standardSQL
WITH `project.dataset.table_with_dups` AS (
SELECT 1 id, 2 value UNION ALL SELECT 1,3 UNION ALL SELECT 1,4 UNION ALL
SELECT 2,5 UNION ALL
SELECT 3,6 UNION ALL SELECT 3,7 UNION ALL
SELECT 4,8 UNION ALL
SELECT 5,9 UNION ALL SELECT 5,10
)
SELECT row[OFFSET(0)].* FROM (
SELECT ARRAY_AGG(t ORDER BY value DESC LIMIT 1) row
FROM `project.dataset.table_with_dups` t
GROUP BY id
)
with result as
Row id value
1 1 4
2 2 5
3 3 7
4 4 8
5 5 10
As you can see it easily dedups table by id leaving row with largest value. Does not matter how many more other columns in that table - above still works (it does not care of schema rather than id and value)
So, now, you can just use above SELECT and insert result into new table or overwrite original, etc. - all in one shot!

Oracle query to find unique occurrences of a column in a table

Here's my table:
ID|2ndID|Value
1|ABC|103
2|ABC|102
3|DEF|103
4|XYZ|105
My query should return all instance of the ID that has only one Value=103 for the 2ndID. It shouldn't return Ids 1 and 2 because apart from 103, ABC has 102 too. 3|DEF on the other hand has only one Value = 103. And I need such rows back. I don't need the 4|XYZ also since value <> 103. Based on the above sample set my result should only be.
3|DEF|103
I can use a group by 2ndID having COUNT(*) =1 which will return all but I don't know how to filter it only to Value = 103.
Thanks in advance.
This should return all the row with a single 2ndId value
select * from
my_table where 2ndId in (
select 2ndId
from my_table
group by 2ndId
having count(*) =1
)
And if you need to enforce the filter for value 103
select * from
my_table where 2ndId in (
select 2ndId
from my_table
group by 2ndId
having count(*) =1
)
and value = 103
This is a standard application of the HAVING clause in aggregate queries. You want to group by the second id, and select only the groups that have only one row and where the min(value) is 103. MIN(value) will be the unique value in the unique row, in the groups that only have one row to begin with; and you don't care about any other groups.
COMMENT: This solution assumes that the combination (second_id, value) is unique - it can't appear in the table more than once, for different id's. I asked the OP in a Comment under the original question to clarify whether this is in fact the case.
with
mytable ( id, second_id, value ) as (
select 1, 'ABC', 103 from dual union all
select 2, 'ABC', 102 from dual union all
select 3, 'DEF', 103 from dual union all
select 4, 'XYZ', 105 from dual
)
-- End of SIMULATED inputs (for testing only, NOT PART OF THE SOLUTION).
-- SQL query begins BELOW THIS LINE. Use your actual table and column names.
select min(id) as id, second_id, min(value) as value
from mytable
group by second_id
having count(*) = 1 and min(value) = 103
;
ID SECOND_ID VALUE
-- --------- -----
3 DEF 103