I store option values and categories in a table.
I want to get one column with all possible combinations of option values.
For example:
Option category ID are (1,2,5)
Option values are {(31,39,55),(61,62),(98,99)}
I want a listing like this, in one column:
31
61
98
31
61
99
31
62
98
31
62
99
39
61
98
39
61
99
39
62
98
39
62
99
55
61
98
55
61
99
55
62
98
55
62
99
Please see below screen shot
Not an answer, just leave it here for you to work with it
Schema, data sample and query you show.
select * into #a from(
select 1 prod,1 id union all
select 1,2 union all
select 1,5 )a
select * into #b from(
select 1 id,31 cat union all
select 1,39 union all
select 1,55 union all
select 2,61 union all
select 2,62 union all
select 5,98 union all
select 5,99 ) b
select * from #a a inner join #b b on a.id=b.id
And this retrieves one row of tree items you look for, in order you need
select b1.cat 'a', b2.cat 'b', b3.cat 'c' from #b b1, #b b2, #b b3, #a a1
where a1.id=b1.id and b2.id>a1.id and b3.id>a1.id and b3.id>b2.id
and b1.cat<b2.cat and b2.cat<b3.cat
order by b1.cat, b2.cat, b3.cat
I'll come back latter
Related
Let' say I have a table like this:
name
math
english
science
Amy
69
70
70
Mike
65
71
63
Jay
66
66
66
I want to create a new column which counts the number of unique value over each row in columns math,english,science;
So this is my expected output:
name
math
english
science
n_unique
Amy
69
70
70
2
Mike
65
71
63
3
Jay
66
66
66
1
For the first row, there are only two kind of score 69, 70 so n_unique is 2,
for the second row, there are 65,71,63 so n_unique is 3,
for the third row, only one score 66, so n_unique is 1;
How to write the query to create such column in Bigquery using SQL?
You can "unpivot" your table, count the distinct grades per student, and then join back to your original table:
with mytable as (
select 'Amy' as name, 69 as math, 70 as english, 70 as science union all
select 'Mike', 65, 71, 63 union all
select 'Jay', 66, 66, 66
),
tmp_unpivot as (
select * from mytable
unpivot(grade for class in(math, english, science))
),
agg as (
select name, count(distinct grade) as n_unique
from tmp_unpivot
group by 1
)
select
mytable.*,
agg.n_unique
from mytable
inner join agg on mytable.name = agg.name
Consider below approach
select *, (
select count(distinct val)
from unnest(regexp_extract_all(format('%t', t), r'\d+')) val
) as n_unique
from your_table t
if applied to sample data in your question - output is
Long time have visited this site and got lot of help. Now I could not find what I'm looking for.
I'm working on Oracle SQL database
Table
columnA ColumnB ColumnC
10A AA 00
10A AA 10
10A AA 20
10A AA 30
10A BB 00
10A BB 10
10A BB 20
10A BB 30
and what I would like to do is extend the columns where there is same data in ColumnA and B like:
columnA ColumnB ColumnC ext.ColumnD ext.ColumnE ext.ColumnF
10A AA 00 10 20 30
10A BB 00 10 20 30
I have tried different pivots, tried lot of suggestions I've found forums but just cant get the result I hope for.
This is my first post so sorry in advance if there is something wrong or information is missing.
Thank you so much in advance!
/ edit
And there would not be same data in ColumnC always or even as many differents. If BB would not have 10 and have differents, it should look something like this:
columnA ColumnB ColumnC ext.ColumnD ext.ColumnE ext.ColumnF
10A AA 00 10 20 30
10A BB 00 17 47
Also goal is to get them increasing order, but that can be done with query, sorting in the first place.
/Edit
Now that I have this one table:
ColumnA ColumnB ColumnC Height1 Height2 Height3 height4
5A 11 A 0 25 50 75
5A 11 B 0 25 50 75
5A 11 C 0 25 50
5A 11 D 0 25 50 75
I have one row in the original table that have random digits which are unique and it needs to go after the height. pivot table with unique row:
ColumnA ColumnB ColumnC Unique ColumnE ColumnF ColumnG ColumnG
5A 11 A 16805097 00
5A 11 A 62366527 25
5A 11 A 65672596 75
5A 11 A 68078617 50
So results would be:
ColumnA ColumnB ColumnC Height1 Unique1 Height2 Unique2 Height3 Unique3 Height4 Unique4
5A 11 A 00 16805097 25 62366527 75 65672596 50 68078617
So if we would take the original question's table, the start point would be like this:
columnA ColumnB ColumnC ColumnD
10A AA 00 699787
10A AA 10 439567
10A AA 20 429456
10A AA 30 122172
10A BB 00 133244
10A BB 10 328311
10A BB 20 247422
10A BB 30 769636
Br
Jan
You can use PIVOT as well and use it we can use row_number() to give a unique number by partition columnA and columnB and then use it in the pivoting clause.
The only disadvantage as you might be aware of is to hard code the values in the PIVOT clause. I have taken max 10 values as of now which you can adjust as per your need.
Note:- The column names generated by PIVOT will be in format of e.g. COLUMND,COLUMNE and so on.. which further can be changed at outer most query as you want. You can also give an alias to MAX(columnC) some_alias but then the columns names will be append it like COLUMND_SOME_ALIAS,COLUMNE_SOME_ALIAS and so on..
SELECT *
FROM
(
SELECT columnA,columnB,columnC,
row_number() OVER (PARTITION BY columnA,columnB ORDER BY columnC) rn_pivot
FROM table1
)
PIVOT
(
MAX(columnC)
FOR rn_pivot IN (1 AS columnD
,2 AS columnE
,3 AS columnF
,4 AS columnG
,5 AS columnH
,6 AS columnI
,7 AS columnJ
,8 AS columnK
,9 AS columnL
,10 AS columnM)
);
If you combine the values in ColumnC into a single CSV list using LISTAGG, you can then use REGEXP_SUBSTR to get the the values in that CSV list. The example below returns up to 5 values for each combination of ColumnA and ColumnB but you can add additional REGEXP_SUBSTR columns if more than 5 are needed.
Query
WITH
sample_data (cola, colb, colc)
AS
(SELECT '10A', 'AA', '00' FROM DUAL
UNION ALL
SELECT '10A', 'AA', '10' FROM DUAL
UNION ALL
SELECT '10A', 'AA', '20' FROM DUAL
UNION ALL
SELECT '10A', 'AA', '30' FROM DUAL
UNION ALL
SELECT '10A', 'BB', '00' FROM DUAL
UNION ALL
SELECT '10A', 'BB', '10' FROM DUAL
UNION ALL
SELECT '10A', 'BB', '20' FROM DUAL
UNION ALL
SELECT '10A', 'BB', '30' FROM DUAL
UNION ALL
SELECT '10A', 'BB', '40' FROM DUAL)
SELECT cola,
colb,
REGEXP_SUBSTR (colc_vals, '[^,]+', 1, 1) as colc_1,
REGEXP_SUBSTR (colc_vals, '[^,]+', 1, 2) as colc_2,
REGEXP_SUBSTR (colc_vals, '[^,]+', 1, 3) as colc_3,
REGEXP_SUBSTR (colc_vals, '[^,]+', 1, 4) as colc_4,
REGEXP_SUBSTR (colc_vals, '[^,]+', 1, 5) as colc_5
FROM ( SELECT cola, colb, LISTAGG (colc, ',') within group (order by colc) AS colc_vals
FROM sample_data
GROUP BY cola, colb);
Result
COLA COLB COLC_1 COLC_2 COLC_3 COLC_4 COLC_5
_______ _______ _________ _________ _________ _________ _________
10A BB 00 10 20 30 40
10A AA 00 10 20 30
I don't know if the title describes my requirements. I have a table C_Bpartner (with C_BPartner_ID as a Primary Key) for employees like this:
name Hiringorderno Orderdate C_Bpartner_ID
A 30 25/02/2002 100
B 47 13/10/2005 101
D 110 22/09/2010 105
and other tables like emp_training:
C_Bpartner_ID TrainingOrderno Orderdate
100 46 14/05/2012
100 58 10/07/2013
101 76 22/10/2015
and emp_penalty:
C_Bpartner_ID PenaltyOrderno Orderdate
105 133 14/05/2012
101 153 25/03/2018
I want the resulting table to be like:
name orderno Orderdate C_Bpartner_ID
A 30 25/02/2012 100
A 46 14/05/2005 100
A 58 10/07/2013 100
B 47 13/10/2005 101
B 76 22/10/2015 101
B 153 25/03/2018 101
D 110 22/09/2010 105
D 133 14/05/2012 105
so, I joined C_BPartner with itself and coalesce them, in order to get a second record for the same C_BPartner_ID. then tried to get the Hiringorderno from C_BPartner bp and join C_BPartner pp with emp_penalty pt(as an example) and get PenaltyOrderno
and combine them with coalesce(bp.Hiringorderno,pt.PenaltyOrderno) and do that for all other tables and for Orderdate as well. but it doesn't duplicate records. it picks the first coalesce parameter and discards the other. like this
coalesce(bp.name,pp.name) coalesce(bp.Hiringorderno,pt.PenaltyOrderno) Hiringorderno PenaltyOrderno
A 30 30 null
B 47 47 153
the emp_penalty record for B is not there.
There's other ways to do this, but I think the most clear and intuitive way is to UNION the 3 queries that you're trying to do.
select name, hiringorderno as orderno, orderdate, C_Bpartner_ID, 'HIRING' as ordertype, null as emp_penalty_ID
from C_Bpartner
union all
select bp.name, trainingorderno, t.orderdate, bp.C_Bpartner_ID, 'TRAINING', null
from emp_training t
join C_Bpartner bp
on bp.C_Bpartner_ID = t.C_Bpartner_ID
union all
select bp.name, PenaltyOrderno, p.orderdate, bp.C_Bpartner_ID, 'PENALTY', p.emp_penalty_ID
from emp_penalty p
join C_Bpartner bp
on bp.C_Bpartner_ID = p.C_Bpartner_ID
;
Edit: I added 2 columns to show 2 common ways to differentiate the union'ed records.
One way is to add a constant string or number to each select statement - that way you can use CASE WHEN ordertype = 'PENALTY' ... or WHERE ordertype = 'TRAINING' to filter your records.
Another way, like you mentioned, is to fill in a column for one of the selects, like emp_penalty_id, but set it to null for the other select statements.
All the select statements being unioned together need to have the same number of columns, with compatible types. The first select statement defines the column names and types for the rest, which is why I didn't need to add column aliases to the second and third selects.
One option is to union 3 queries:
SQL> with
2 c_bpartner (name, hiringorderno, orderdate, c_bpartner_id) as
3 (select 'A', 30, date '2002-02-25', 100 from dual union all
4 select 'B', 47, date '2005-10-13', 101 from dual union all
5 select 'D', 110,date '2010-09-22', 105 from dual
6 ),
7 emp_training(c_bpartner_id, trainingorderno, orderdate) as
8 (select 100, 46, date '2012-05-14' from dual union all
9 select 100, 58, date '2013-07-10' from dual union all
10 select 101, 76, date '2015-10-22' from dual
11 ),
12 emp_penalty (c_bpartner_id, penaltyorderno, orderdate) as
13 (select 105, 133, date '2012-05-14' from dual union all
14 select 101, 153, date '2018-03-25' from dual
15 )
16 select c.name, c.hiringorderno as orderno, c.orderdate, c.c_bpartner_id
17 from c_bpartner c
18 union all
19 select c.name, t.trainingorderno, t.orderdate, t.c_bpartner_id
20 from c_bpartner c join emp_training t on t.c_bpartner_id = c.c_bpartner_id
21 union all
22 select c.name, p.penaltyorderno, p.orderdate, p.c_bpartner_id
23 from c_bpartner c join emp_penalty p on p.c_bpartner_id = c.c_bpartner_id
24 order by 1, 2;
N ORDERNO ORDERDATE C_BPARTNER_ID
- ---------- ---------- -------------
A 30 25/02/2002 100
A 46 14/05/2012 100
A 58 10/07/2013 100
B 47 13/10/2005 101
B 76 22/10/2015 101
B 153 25/03/2018 101
D 110 22/09/2010 105
D 133 14/05/2012 105
8 rows selected.
SQL>
Query returning 2 values from table TBL_CHARGES:
Range_in_hrs Range_to_hours charges
4 48 5
48 70 10
70 90 20
Select charges from table if range 47.59 is passed the return charge should be 5. If 48.00 is passed the charges will be 5.
If 48.01 is passed the charges should be 10.
I am trying this
SELECT *
FROM TBL_CHARGES
WHERE 48.00 between Range_in_hrs and Range_to_hours
But it does not works.
Sounds like you need to avoid using BETWEEN and instead use explicit ranges, like so:
select *
from tbl_charges
where 48 > range_in_hrs
and 48 <= range_to_hours;
And here's an example that shows the output you might get with various different values:
with tbl_charges as (select 4 range_in_hours, 48 range_to_hours, 5 charges from dual union all
select 48 range_in_hours, 70 range_to_hours, 10 charges from dual union all
select 70 range_in_hours, 90 range_to_hours, 20 charges from dual),
vals as (select 4 val from dual union all
select 4.01 val from dual union all
select 47.59 val from dual union all
select 48 val from dual union all
select 48.01 val from dual union all
select 70 val from dual union all
select 71 val from dual)
select vals.val,
tc.charges
from vals
left outer join tbl_charges tc on (vals.val > tc.range_in_hours and vals.val <= tc.range_to_hours);
VAL CHARGES
---------- ----------
4
4.01 5
47.59 5
48 5
48.01 10
70 10
71 20
My problem got solved by this query.
SELECT *
FROM TBL_CHARGES
WHERE 48.00 between Range_in_hrs||'.01' and Range_to_hours||'.00'
SELECT charges
FROM TBL_CHARGES
WHERE ceil(to_number('48.01')) between Range_in_hrs and Range_to_hours
Use Replace and Ceil.
I have an alphanumeric data like:
1
1a
1b
2
2b
10
10a
If I sort this data, output will be like:
1
1a
10
10a
2
2b
But I want output as:
1
1a
2
2b
10
10a
How to get this output with Oracle command?
So, as I understand, you want to sort by numeric part of your data. For this purpose you can use regular expression (to extract the numeric part) like this:
SQL> select str from
2 (
3 select '1' str from dual union all
4 select '1a' from dual union all
5 select '1b' from dual union all
6 select '2' from dual union all
7 select '2b' from dual union all
8 select '10' from dual union all
9 select '10a' from dual
10 ) t
11 order by to_number(regexp_substr(str, '^[[:digit:]]*')), str
12 /
STR
---
1
1a
1b
2
2b
10
10a
You can also do the same by separating number and alphanumeric sorting order in order by clause. check below example:
SELECT tt.qdef_grid
FROM qgdm_qdef tt
ORDER BY to_number(substr(tt.qdef_grid,2,2)), substr(tt.qdef_grid,1,1);