transpose column to row oracle - sql

I have a query returned value in this form (query return more than 50 columns).
1-99transval 100-200transval 200-300transval ... 1-99nontransval 100...
50 90 80 67 58
For a row value. I want these details to be converted into columns and take the following shape:
Range Transval NonTransval
1-99 50 67
100-200 90 58

In pure SQL, it will need a lot of coding because you will have to manually put the range as there is no relation between the values and the range at all. Had there been a relationship, you could use CASE expression and build the range dynamically.
SQL> WITH DATA AS
2 (SELECT 50 "1-99transval",
3 90 "100-200transval",
4 80 "200-300transval",
5 67 "1-99nontransval",
6 58 "100-200nontransval",
7 88 "200-300nontransval"
8 FROM dual
9 )
10 SELECT '1-99' range,
11 "1-99transval" transval,
12 "1-99nontransval" nontransval
13 FROM DATA
14 UNION
15 SELECT '100-200' range,
16 "100-200transval",
17 "100-200nontransval" nontransval
18 FROM DATA
19 UNION
20 SELECT '200-300' range,
21 "200-300transval",
22 "200-300nontransval" nontransval
23 FROM DATA;
RANGE TRANSVAL NONTRANSVAL
------- ---------- -----------
1-99 50 67
100-200 90 58
200-300 80 88
From Oracle database 11g Release 1 and above, you could use UNPIVOT
SQL> WITH DATA AS
2 (SELECT 50 "1-99transval",
3 90 "100-200transval",
4 80 "200-300transval",
5 67 "1-99nontransval",
6 58 "100-200nontransval",
7 88 "200-300nontransval"
8 FROM dual
9 )
10 SELECT *
11 FROM DATA
12 UNPIVOT( (transval,nontransval)
13 FOR RANGE IN ( ("1-99transval","1-99nontransval") AS '1-99'
14 ,("100-200transval","100-200nontransval") AS '100-200'
15 ,("200-300transval","200-300nontransval") AS '200-300'));
RANGE TRANSVAL NONTRANSVAL
------- ---------- -----------
1-99 50 67
100-200 90 58
200-300 80 88
Above, in your case you need to replace the WITH clause with your existing query as a sub-query. You need to include other columns in the UNION.
In PL/SQL, you could (ab)use EXECUTE IMMEDIATE and get the "range" by extracting the column names in dynamic sql.
Although, it would be much better to modify/rewrite your existing query which you have not shown yet.

If you are using Oracle 11g version then you can use the UNPIVOT feature.
CREATE TABLE DATA AS
SELECT 50 "1-99transval",
90 "100-200transval",
80 "200-300transval",
67 "1-99nontransval",
58 "100-200nontransval",
88 "200-300nontransval"
FROM dual
SELECT *
FROM DATA
UNPIVOT( (Transval,NonTransval) FOR Range IN ( ("1-99transval","1-99nontransval") as '1-99'
,("100-200transval","100-200nontransval") as '100-200'
,("200-300transval","200-300nontransval") as '200-300'))
http://sqlfiddle.com/#!4/c9747/3/0

Related

Display rows where multiple columns are different

I have data that looks like this. Thousands of rows returned, but this is just a sample.
Most days have the same numbers in them, but some do not. Note that ID 1 and 5 have identical numbers every day.
ID
Sunday
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
1
26
26
26
26
26
26
26
2
44
44
30
30
44
44
44
3
55
55
55
55
80
90
55
4
12
12
43
43
43
43
43
5
36
36
36
36
36
36
36
I'd like to only return rows where the days of the week have different numbers.
In this case, the only IDs returned should be 2, 3 & 4.
What would I want this query to look like?
Thanks!
One idea that should work in most RDBMS (with some syntax tweaks) is the following.
This is SQL Server compatible: pivot the days into rows and count the distinct values and filter accordingly:
select id
from t
cross apply (
select Count(distinct d) from (
values(sunday),(monday),(tuesday),(wednesday),(thursday),(friday),(saturday)
)d(d)
)d(v)
where d.v>1

TRUNC(NVL(COLUMN, '2')) ORA-01722: invalid number

I have a column in table which is varchar2(3) style column. This column has some nulls and when I try to run following query it runs for some records but when I scroll to some record I get ORA-01722: invalid number error.
Query used:
Select TRUNC(NVL(COLUMN, '2'))
from TABLE;
Also I ran distinct on column to see what values it has.
Select distinct COLUMN
from TABLE;
I got following results:
1
2 62
3 90
4 70
5 82
6 71
7 05
8 21
9 81
10 66
11 12
12 95
13 02
14 91
15 92
16 94
17 01
18 65
19 30
20 20
21
22 50
23 63
24 51
25 64
26 09
Why am I getting this error and how can I do this without getting error?
https://docs.oracle.com/cd/B19306_01/server.102/b14200/functions200.htm
Because you want to trunc a string, but TRUNC function is for number or date .
This function takes as an argument any numeric datatype or any nonnumeric datatype that can be implicitly converted to a numeric datatype
Maybe one of your string value cannot be converted to number
edit : your 21t value is not a number and is not null, you should trim your column
SELECT trunc(nvl(trim(column),'2'))
FROM table;

Aggregate result from query by quarter SQL

Lets say I have a table which holds all exports for some time back in Microsoft SQL database:
Name:
ExportTable
Columns:
id - numeric(18)
exportdate - datetime
In order to get the number of exports per week I can run the following query:
SELECT DATEPART(ISO_WEEK,[exportdate]) as 'exportdate', count(exportdate) as 'totalExports'
FROM [ExportTable]
Group By DATEPART(ISO_WEEK,[exportdate])
order by exportdate;
Returns:
exportdate totalExports
---------- ------------
27 13
28 12
29 15
30 8
31 17
32 10
33 7
34 15
35 4
36 18
37 10
38 14
39 14
40 21
41 19
Would it be possible to aggregate the week results by quarter so the output becomes something like the bellow?
UPDATE
Sorry for not being crystal clear, I would like the current result to add upp with previous result up to a new quarter.
Note week 41 contains 21+19 = 40
Week 39 contains 157 (13+12+15+8+17+10+7+15+4+18+10+14+14)
exportdate totalExports Quarter
---------- ------------ -------
27 13 3
28 25 3
29 40 3
30 48 3
31 65 3
32 75 3
33 82 3
34 97 3
35 101 3
36 119 3
37 129 3
38 143 3
39 157 3 -- Sum of 3 Quarter values.
40 21 4 -- New Quarter show current week value
41 40 4 -- (21+19)
You can use this.
SELECT
DATEPART(ISO_WEEK,[exportdate]) as 'exportdate'
, SUM( count(exportdate) ) OVER ( PARTITION BY DATEPART(QUARTER,MIN([exportdate])) ORDER BY DATEPART(ISO_WEEK,[exportdate]) ROWS UNBOUNDED PRECEDING ) as 'totalExports'
, DATEPART(QUARTER,MIN([exportdate])) [Quarter]
FROM [ExportTable]
Group By DATEPART(ISO_WEEK,[exportdate])
order by exportdate;
You could use a case statement to separate the dates into quarters.
e.g.
CASE
WHEN EXPORT_DATE BETWEEN '1' AND '4' THEN 1
WHEN Export_Date BETWEEN '5' and '9' THEN 2
ELSE 0 AS [Quarter]
END
Its just an example but you get the idea.
You could then use the alias from the case
SELECT DATEPART(ISO_WEEK,[exportdate]) as 'exportdate', count(exportdate) as 'totalExports', DATEPART(quarter,[exportdate]) as quarter FROM [ExportTable] Group By DATEPART(ISO_WEEK,[exportdate]), DATEPART(quarter,[exportdate]) order by exportdate;

Calculate SUM Column Wise using dinaymic query in SQL Server

id varname 1area 2area 3area 4area
------------------------------------
1 abc 345 3.7 34 87
1 pqr 46 67 78 55
1 lmn 67 99 33 44
2 xyz 78 78 33 32
I need to calculate SUM of column query.
Is it possible to get column count using while loop?
You probably want to do a SUM() of the Narea column group by your id column like
select id, sum(1area),
sum(2area), sum(3area), sum(4area)
from tbl1
group by id;

Get MAX value of a group for each month TSQL

I have a TSQL query which gives a max value of the trend data for the given result set. I would like to get this data based on each month's result. (I have a datetime column in the result set ). If I select data for three months it has to give this vaules for each month. Right now it looks for the max values and give the same result for all the months.
Below is the expression i use to get the trend result. It's part of select statement with number of other columns.
select col1, col2, sampledatecollected, (Select MAX(AvailMemSlope) FROM SlopeCTE) * MetricID + (Select MAX (AvailMemIntercept) FROM InterceptCTE) AS AvailMemTrend
I think i might need to do something like this but given the expression i'm little confused as to how to get the desired results
select name, max(value)
from tbl1
group by name
CPUTrend id the data i get from the expression i specified in the first query.
sample data:
Date AVGCPU MAXCPU CPUTrend
8/22/2016 20 40 44
8/23/2016 20 40 44
8/24/2016 20 40 44
8/25/2016 20 40 44
9/22/2016 20 50 44
9/23/2016 20 50 44
9/24/2016 20 50 44
Expected result:
Date AVGCPU MAXCPU CPUTrend
8/22/2016 20 40 32
8/23/2016 20 40 32
8/24/2016 20 40 32
8/25/2016 20 40 32
9/22/2016 20 50 44
9/23/2016 20 50 44
9/24/2016 20 50 44
Right now all i get is 44 as it's the maximum value.
I think you just want a subquery:
with t as (
select col1, col2, sampledatecollected,
(Select MAX(AvailMemSlope) FROM SlopeCTE) * MetricID +
(Select MAX (AvailMemIntercept) FROM InterceptCTE) AS AvailMemTrend
from ?? -- the SQL in your question is incomplete
)
select year(sampledatecollected), month(sampledatecollected),
max(AvailMemTrend)
from t
group by year(sampledatecollected), month(sampledatecollected)
order by year(sampledatecollected), month(sampledatecollected);