I have some information on student name and their roll no -
And I want to split them into 3 sets of column like below. The total no of rows should always be ceiling value of (# of rows/3)
You can do this with conditional aggregation. However, SQL tables represent unordered sets, so which values end up where is arbitrary:
select max(case when seqnum % 3 = 0 then name end) as name_1,
max(case when seqnum % 3 = 0 then roll end) as roll_1,
max(case when seqnum % 3 = 1 then name end) as name_2,
max(case when seqnum % 3 = 1 then roll end) as roll_2,
max(case when seqnum % 3 = 2 then name end) as name_3,
max(case when seqnum % 3 = 2 then roll end) as roll_3
from (select t.*, row_number() over (order by (select null)) - 1 as seqnum
from t
) t
group by floor(seqnum / 3);
If you have an ordering column, then use it instead of (select null).
Related
I have a table that looks similar to this here:
I would like to able to combine all that data when they have the same Id.
Which would look like this:
Use conditional aggregation:
select id,
max(case when seqnum = 1 then section end) as section1,
max(case when seqnum = 1 then value1 end) as section1_value1,
max(case when seqnum = 1 then value2 end) as section1_value2,
max(case when seqnum = 2 then section end) as section2,
max(case when seqnum = 2 then value1 end) as section2_value1,
max(case when seqnum = 2 then value2 end) as section2_value2
from (select t.*,
row_number() over (partition by id order by section) as seqnum
from t
) t
group by id;
Users have multiple certificates which might be of 3 different types. They may hold multiple certificates of those types. I would like to put them into a single record anticipating that they will have a max of five certificates of each type.
I've written a query that will find the type and put its information into an appropriately named column but still get one row per certificate.
Data shape is:
Name, cert_Type, Cert Name, cert_State, Cert_Expiration
JOE, Equipment, NULL, Operator, 01/30/2022
JOE Equipment, Rigger, 12/31/2021
JOE License, Maryland, 08/12/2025
I'm doing a group by, but still need some aggregating function to get the desired result which might look like this:
| UserName| userID|Cred_Type_1|Cred_1|Type_1_Cred_1_ Expires|Type_1_Cred_2|Type_1_Cred_2_Expires|Cred_type_2|Type2_State |Type_2_expires|
| ----------- | ----------- |-------------|-------------|------------|------------|-----------|-----------|---|---|
|Joe|123|Equipment|Operator|01/30/2022|Rigger|12/31/2021|License | Maryland|08/12/2025|
Note that there is no aggregate here, not counting or averaging or summing. Is there another aggregate function that will do this?
If I understand correctly, you can use row_number() and conditional aggregation:
select userid, username,
max(case when seqnum = 1 then cert_type end),
max(case when seqnum = 1 then cert_name end),
max(case when seqnum = 1 then cert_state end),
max(case when seqnum = 1 then cert_expiration end),
max(case when seqnum = 2 then cert_type end),
max(case when seqnum = 2 then cert_name end),
max(case when seqnum = 2 then cert_state end),
max(case when seqnum = 2 then cert_expiration end),
max(case when seqnum = 3 then cert_type end),
max(case when seqnum = 3 then cert_name end),
max(case when seqnum = 3 then cert_state end),
max(case when seqnum = 3 then cert_expiration end),
from (select t.*,
row_number() over (partition by userid order by cert_expiration desc) as seqnum
from t
) t
group by userid, username;
I would like to pivot results from a table into a new structure. So that it can map all the children to the parent product.
Current Result
Parent_Prod_Num|Child_Prod_Num|Child_Prod_Code|Child_Prod_Name
1|11|a123|a
1|12|b123|ab
1|13|c123|abc
Expected Result
Parent_Prod_Num|Child_Prod_Num_1| Child_Prod_Code_1|Child_Prod_Name_1| Child_Prod_Num_2| Child_Prod_Code_2|Child_Prod_Name_2| Child_Prod_Num_3| Child_Prod_Code_3|Child_Prod_Name_3
1|11|a123|a|12|b123|ab|13|c123|abc
For a fixed maximum number of children per parent, you can enumerate the rows with row_number(), then pivot with conditional aggregation:
select parent_prod_num,
max(case when rn = 1 then child_prod_num end) as child_prod_num_1,
max(case when rn = 1 then child_prod_code end) as child_prod_code_1,
max(case when rn = 1 then child_prod_name end) as child_prod_name_1,
max(case when rn = 2 then child_prod_num end) as child_prod_num_2,
max(case when rn = 2 then child_prod_code end) as child_prod_code_2,
max(case when rn = 2 then child_prod_name end) as child_prod_name_2,
max(case when rn = 3 then child_prod_num end) as child_prod_num_3,
max(case when rn = 3 then child_prod_code end) as child_prod_code_3,
max(case when rn = 3 then child_prod_name end) as child_prod_name_3
from (
select t.*, row_number() over(partition by parent_prod_num order by child_prod_num) rn
from mytable t
) t
group by parent_prod_num
Here is the table structure
ID TypeX TypeXDesc XDate TypeCodeY
040001 3669 Unspecified Cat 2005-08-08 1
040001 3669 Unspecified Cat 2006-08-29 2
040001 37515 Tear Film 2005-08-08 1
040001 37999 Disor 2004-07-22 1
Transform above table INTO below USING PIVOT
ID TypeX_1 TypeXDesc_1 XDate_1 TypeCodeY_1 TypeX_2 TypeXDesc_2 XDate_2 TypeCodeY_2 TypeX_3 TypeXDesc_3 XDate_3 TypeCodeY_3
040001 3669 Unspecified Cat 2005-08-08 1 37515 Tear Film 2005-08-08 1 37999 Disor 2004-07-22 1
Look at the same TypeX code but XDate is different and we need to get Min(XDate) so first row is qualified not the second row.
You can accomplish this using conditional aggregation. In this case, you can enumerate the rows with within typex/id groups using row_number(). You can enumerate the groups with with typex/id using dense_rank().
Then, use conditional aggregation:
select t.id,
max(case when grpnum = 1 and seqnum = 1 then typex end) as typex_1,
max(case when grpnum = 1 and seqnum = 1 then TypeXDesc end) as TypeXDesc_1,
max(case when grpnum = 1 and seqnum = 1 then XDate end) as XDate_1,
max(case when grpnum = 1 and seqnum = 1 then TypeCodeY end) as TypeCodeY_1,
max(case when grpnum = 2 and seqnum = 1 then typex end) as typex_12,
max(case when grpnum = 2 and seqnum = 1 then TypeXDesc end) as TypeXDesc_2,
max(case when grpnum = 2 and seqnum = 1 then XDate end) as XDate_2,
max(case when grpnum = 2 and seqnum = 1 then TypeCodeY end) as TypeCodeY_3,
max(case when grpnum = 3 and seqnum = 1 then typex end) as typex_1,
max(case when grpnum = 3 and seqnum = 1 then TypeXDesc end) as TypeXDesc_3,
max(case when grpnum = 3 and seqnum = 1 then XDate end) as XDate_3,
max(case when grpnum = 3 and seqnum = 1 then TypeCodeY end) as TypeCodeY_3
from (select t.*,
row_number() over (partition by id, typex order by xdate as seqnum,
dense_rank() over (partition by id order by typex) as grpnum
from t
) t
group by id;
Have a table:
Nomber Sce SceValue
10 A a1b2c3
20 C d2v3b4
10 B 42b2c3
10 B 5978c3
20 A edr432
I need to create the following listing using a view where there all possible "Sce" and "SceValue" pairs are shown for each individual "Nomber" (9 pairs maximum):
Nomber Sce1 SceValue1 Sce2 SceValue2 ... Sce9 SceValue9
10 A a1b2c3 B 42b2c3 B 5978c3
20 C d2v3b4 A edr432
I would like to achieve this using a View. Is this possible?
You can use conditional aggregation:
select number,
max(case when seqnum = 1 then Sce end) as sce_1,
max(case when seqnum = 1 then SceValue end) as SceValue_1,
max(case when seqnum = 2 then Sce end) as sce_2,
max(case when seqnum = 2 then SceValue end) as SceValue_2,
. . .
max(case when seqnum = 9 then Sce end) as sce_9,
max(case when seqnum = 9 then SceValue end) as SceValue_9
from (select t.*,
row_number() over (partition by nomber order by sce) as seqnum
from t
) t
group by nomber;