sql inner join - multicolumn - sql

can anyone help me with this sql query?
I have the following query:
select rps.res, rps.tar, rps.uni, rps.val
from TABLEX rps
where rps.res = '1'
or rps.res = '2'
or rps.res = '3'
order by rps.tar, rps.res asc
The Output looks like:
res | tar | uni | val
1 | A | B | 10
2 | A | B | 15
3 | A | B | 20
The output I would like to have is:
tar | uni | val1 | val2 | val3
Thanks in advance!

You can directly apply Conditional Aggregation :
select tar, uni,
max(case when tar = 1 then val end) as val1,
max(case when tar = 2 then val end) as val2,
max(case when tar = 3 then val end) as val3
from tab
group by tar, uni;

You can pivot using conditional aggregation and use row_number() for the numbering:
select tar, uni,
max(case when seqnum = 1 then val end) as val_1,
max(case when seqnum = 2 then val end) as val_2,
max(case when seqnum = 3 then val end) as val_3
from (select t.*,
row_number() over (partition by tar, uni order by val) as seqnum
from t
) t
group by tar, uni;

Related

Joining multiple rows into a single row without aggregation using Oracle11g

The below link shows the same question that was asked which I want to ask and the code which was provided to answer the query, I used this query (modified it) but please how do I add a join table and a where clause in this query? see below the code I have added to the code in the link below but I am getting error messages. I would like the output to be same as the one provided in the link below
Joining multiple rows into a single row without aggregation [Oracle]
Bare in mind that the desired result provided in the link is my same desired results.
Below is the script which I have modified:
select max(case when seqnum = 1 then p.PERSONID end) as PersonID,
max(case when seqnum = 1 then t.PHONEID end) as PhoneID1,
max(case when seqnum = 1 then t.PHONENUM end) as PhoneNum1,
max(case when seqnum = 1 then t.TYPE end) as Type1,
max(case when seqnum = 1 then t.ISPRIMARY end) as IsPrimary1,
max(case when seqnum = 1 then t.ROWSTAMP1 end) as Rowstamp1,
max(case when seqnum = 2 then t.PHONEID end) as PhoneID2,
max(case when seqnum = 2 then t.PHONENUM end) as PhoneNum2,
max(case when seqnum = 2 then t.TYPE end) as Type2,
max(case when seqnum = 2 then t.ISPRIMARY end) as IsPrimary2,
max(case when seqnum = 2 then t.ROWSTAMP1 end) as Rowstamp2,
max(case when seqnum = 3 then t.PHONEID end) as PhoneID3,
max(case when seqnum = 3 then t.PHONENUM end) as PhoneNum3,
max(case when seqnum = 3 then t.TYPE end) as Type3,
max(case when seqnum = 3 then t.ISPRIMARY end) as IsPrimary3,
max(case when seqnum = 3 then t.ROWSTAMP1 end) as Rowstamp3
from (test1.phone t left join test2.person p
ON t1.PERSONID = t2.PERSONID
where t2.PERSONID = 'MXSDFD'
) t;
rownum as seqnum
from t
Use PIVOT:
select personid,
"1_PHONEID" AS phoneid1,
"1_PHONENUM" AS phonenum1,
"1_TYPE" AS type1,
"1_ISPRIMARY" AS isprimary1,
"1_ROWSTAMP1" AS rowstamp1,
"2_PHONEID" AS phoneid2,
"2_PHONENUM" AS phonenum2,
"2_TYPE" AS type2,
"2_ISPRIMARY" AS isprimary2,
"2_ROWSTAMP1" AS rowstamp2,
"3_PHONEID" AS phoneid3,
"3_PHONENUM" AS phonenum3,
"3_TYPE" AS type3,
"3_ISPRIMARY" AS isprimary3,
"3_ROWSTAMP1" AS rowstamp3
from (
SELECT p.personid,
t.phoneid,
t.phonenum,
t.type,
t.isprimary,
t.rowstamp1,
ROW_NUMBER() OVER (
PARTITION BY p.personid ORDER BY t.isprimary DESC, t.rowstamp1 DESC
) AS seqnum
FROM person p
left join phone t
ON ( t.PERSONID = p.PERSONID )
where t.PERSONID = 'MXSDFD'
)
PIVOT (
MAX( phoneid ) AS phoneid,
MAX( phonenum ) AS phonenum,
MAX( type ) AS type,
MAX( isprimary ) AS isprimary,
MAX( rowstamp1 ) AS rowstamp1
FOR seqnum IN ( 1, 2, 3 )
)
Which, for the sample data:
CREATE TABLE person ( personid, name ) AS
SELECT 'MXSDFD', 'Alice' FROM DUAL;
CREATE TABLE phone ( personid, phonenum, phoneid, type, isprimary, rowstamp1 ) AS
SELECT 'MXSDFD', '012346', 1, 'A', 'N', TIMESTAMP '2020-10-13 09:00:00' FROM DUAL UNION ALL
SELECT 'MXSDFD', '555666', 3, 'C', 'N', TIMESTAMP '2020-10-13 08:30:00' FROM DUAL UNION ALL
SELECT 'MXSDFD', '987654', 2, 'B', 'Y', TIMESTAMP '2020-10-13 08:00:00' FROM DUAL;
Outputs:
PERSONID | PHONEID1 | PHONENUM1 | TYPE1 | ISPRIMARY1 | ROWSTAMP1 | PHONEID2 | PHONENUM2 | TYPE2 | ISPRIMARY2 | ROWSTAMP2 | PHONEID3 | PHONENUM3 | TYPE3 | ISPRIMARY3 | ROWSTAMP3
:------- | -------: | :-------- | :---- | :--------- | :--------------------------- | -------: | :-------- | :---- | :--------- | :--------------------------- | -------: | :-------- | :---- | :--------- | :---------------------------
MXSDFD | 2 | 987654 | B | Y | 13-OCT-20 08.00.00.000000000 | 1 | 012346 | A | N | 13-OCT-20 09.00.00.000000000 | 3 | 555666 | C | N | 13-OCT-20 08.30.00.000000000
db<>fiddle here
You seem to want logic like this:
select max(case when seqnum = 1 then t.PERSONID end) as PersonID,
max(case when seqnum = 1 then t.PHONEID end) as PhoneID1,
max(case when seqnum = 1 then t.PHONENUM end) as PhoneNum1,
max(case when seqnum = 1 then t.TYPE end) as Type1,
max(case when seqnum = 1 then t.ISPRIMARY end) as IsPrimary1,
max(case when seqnum = 1 then t.ROWSTAMP1 end) as Rowstamp1,
max(case when seqnum = 2 then t.PHONEID end) as PhoneID2,
max(case when seqnum = 2 then t.PHONENUM end) as PhoneNum2,
max(case when seqnum = 2 then t.TYPE end) as Type2,
max(case when seqnum = 2 then t.ISPRIMARY end) as IsPrimary2,
max(case when seqnum = 2 then t.ROWSTAMP1 end) as Rowstamp2,
max(case when seqnum = 3 then t.PHONEID end) as PhoneID3,
max(case when seqnum = 3 then t.PHONENUM end) as PhoneNum3,
max(case when seqnum = 3 then t.TYPE end) as Type3,
max(case when seqnum = 3 then t.ISPRIMARY end) as IsPrimary3,
max(case when seqnum = 3 then t.ROWSTAMP1 end) as Rowstamp3
from (select t.*, rownum as seqnum
from test1.phone t join
test2.person p
on t.PERSONID = p.PERSONID
where p.PERSONID = 'MXSDFD'
) t;
That said, you don't seem to need the join at all, because you are filtering on the join key (it is in both tables). So:
from (select t.*, rownum as seqnum
from test1.phone t
where t.PERSONID = 'MXSDFD'
) t

Convert Table to another format in MSSQL

I am facing a problem with MS-SQL in getting output from a table in a particular format.
Name | StringValue | Parent_ID
FieldName | TestHeader1 | 3
FieldValue | ValueForTestHeader1 | 3
FieldName | TestHeader2 | 6
FieldValue | ValueForTestHeader2 | 6
And I want to select data from this table as follows:
TestHeader1 | TestHeader2
ValueForTestHeader1 | ValueForTestHeader2
Any help would be highly appreciated!
use conditional aggregation
select max(case when parent_id=3 then stringvalue) as col1,
max(case when parent_id=6 then stringvalue) as col2
from tablename
group by parent_id
You can do conditional aggregation by using row_number() & dense_rank():
select max(case when seq1 = 1 then stringvalue end),
max(case when seq1 = 2 then stringvalue end)
from (select t.*,
dense_rank() over (order by parent_id) as seq1,
row_number() over (partition by parent_id order by stringvalue) seq2
from table t
) t
group by seq2;

Is it possible to convert multiple rows into a singular row in oracle

I am looking to return one row that merges multiple rows so for the example table:
ID | VAL1 | VAL2
1 | v1 | v2
1 | v3 |v4
I would like to return:
ID|VAL1|VAL2|VAL1_1|VAL2_1
1 | v1 | v2 | v3 | v4
Where ID|VAL1|VAL2|VAL1_1|VAL2_1 are the column headers
I dont believe a pivot can work as the values (v1 etc) can be any value.
Any help would be greatly appreciated
If you want a dynamic pivot, then you need dynamic SQL. But, you can do what you want with conditional aggregation:
select id,
max(case when seqnum = 1 then val1 end) as val1,
max(case when seqnum = 1 then val2 end) as val2,
max(case when seqnum = 2 then val1 end) as val1_1,
max(case when seqnum = 2 then val2 end) as val2_1
from (select t.*, row_number() over (partition by id order by id) as seqnum
from t
) t
group by id;
If your rows are ordered in a particular way, then you should modify the order by.

Calculation between row_value at sqlite3

I have the following table.
| col_num | row_num | value |
|---------|----------|-----------|
| 1 | 3 | 5(value1) |
| 2 | 4 | 7(value2) |
| 5 | 1 | 8(value3) |
Now I want to conduct (value2) / (sqrt(value1)*sqrt(value2)) by querying in sqlite3.
Do you have any idea for this?
Try something like this.
select col_num, row_num,
value/((select sqrt(value) from tbl where row_num = 3) * sqrt(value)) as newValue
from tbl where row_num = 4;
It is unclear how you know what is value1, value2, and value3. You can use conditional aggregation. If you were to use row_num, then it would look like:
select (max(case when row_number = 4 then value end) /
sqrt(max(case when row_nunmber = 3 then value end) *
max(case when row_nunmber = 1 then value end)
)
)
from t;
EDIT:
If the valueX is actually part of the value itself:
select max(case when value like '%(value2)' then substring_index(value, '(', 1) + 0 end) /
sqrt(max(case when '%(value1)' then substring_index(value, '(', 1) + 0 end) *
max(case when '%(value2)' then substring_index(value, '(', 1) + 0 end)
)
)
from t;

Aggregating a unique pair of column values from the same table based on a common column value

I have the following table:
my_table
------------------------
| common_id | uniq_val |
------------------------
| 1 | foo |
------------------------
| 1 | bar |
------------------------
And I want to aggregate values from it such that the resulting query looks like:
DESIRED RESULT
---------------------------------------
| common_id | uniq_val_1 | uniq_val_2 |
---------------------------------------
| 1 | foo | bar |
---------------------------------------
OR
---------------------------------------
| common_id | uniq_val_1 | uniq_val_2 |
---------------------------------------
| 1 | bar | foo |
---------------------------------------
So I've written the query:
SELECT t1.common_id, t1.uniq_val, t2.uniq_val
FROM my_table t1 JOIN my_table AS t2
ON t1.common_id=t2.common_id
WHERE t1.uniq_val!=t2.uniq_val;
Which results in
RESULTING SELECT
---------------------------------------
| common_id | uniq_val_1 | uniq_val_2 |
---------------------------------------
| 1 | foo | foo |
---------------------------------------
| 1 | bar | bar |
---------------------------------------
But I only need one of those columns, so I should be able to do a GROUP BY t1.common_id, like:
SELECT t1.common_id, t1.uniq_val, t2.uniq_val
FROM my_table t1 JOIN my_table AS t2
ON t1.common_id=t2.common_id
WHERE t1.uniq_val!=t2.uniq_val
GROUP BY t1.common_id;
Unfortunately this returns the error:
ERROR: column "t1.uniq_val" must appear in the GROUP BY clause or be used in an aggregate function
Can anyone point out the error in my logic?
How about simple aggregation?
select common_id, min(uniq_val) as uniq_val_1, max(uniq_val) as uniq_val_2
from my_table
group by common_id;
you can try distinct on
SELECT distinct on (t1.common_id) t1.common_id, t1.uniq_val, t2.uniq_val
FROM my_table t1 JOIN my_table AS t2
ON t1.common_id=t2.common_id
WHERE t1.uniq_val!=t2.uniq_val;
I think it will produce what you need!
This will handle up to 10 uniq_val values per common_id. You can remove or add to account for fewer or more uniq_val values if needed.
See a demonstration here with common_id values that have varying counts of uniq_val values:
http://sqlfiddle.com/#!15/e2c87/1/0
select common_id,
max(case when rn = 1 then uniq_val else null end) as uniq_val_1,
max(case when rn = 2 then uniq_val else null end) as uniq_val_2,
max(case when rn = 3 then uniq_val else null end) as uniq_val_3,
max(case when rn = 4 then uniq_val else null end) as uniq_val_4,
max(case when rn = 5 then uniq_val else null end) as uniq_val_5,
max(case when rn = 6 then uniq_val else null end) as uniq_val_6,
max(case when rn = 7 then uniq_val else null end) as uniq_val_7,
max(case when rn = 8 then uniq_val else null end) as uniq_val_8,
max(case when rn = 9 then uniq_val else null end) as uniq_val_9,
max(case when rn = 10 then uniq_val else null end) as uniq_val_10
from(
select row_number() over (partition by common_id order by common_id, uniq_val) as rn,
common_id,
uniq_val
from my_table
order by common_id, uniq_val) x
group by common_id
order by common_id