Pivot query Oracle SQL - oracle

I have the below table and I am trying to write an Oracle select query that would result in the second table.
I understand I have to use Pivot but I can't figure at all how to do.
MSGID
KEY
COLVALUE
15
height
18
15
length
19
15
width
20
15
notImportant
xxx
16
height
21
16
length
22
16
width
23
16
notImportant
xxx
17
height
24
17
length
25
17
width
26
17
notImportant
xx
Desired result:
MsgID
height
length
width
15
18
19
20
16
21
22
23
17
24
25
26
Tried the below code but without success....
select MSGID, HEIGHT, LENGTH, WIDTH
from (select MSGID, KEY, COLVALUE
from table )
PIVOT
(
max(COLVALUE)
FOR KEY IN ('HEIGHT','LENGTH','WIDTH')
)
Do you have any tips?

Here's one option:
SQL> select msgid,
2 max(case when key = 'height' then colvalue end) height,
3 max(case when key = 'length' then colvalue end) length,
4 max(case when key = 'width' then colvalue end) width
5 from test
6 group by msgid
7 order by msgid;
MSGID HEIGHT LENGTH WIDTH
---------- ---------- ---------- ----------
15 18 19 20
16 21 22 23
17 24 25 26
SQL>
Or, with pivot:
SQL> select *
2 from test
3 pivot
4 (max(COLVALUE)
5 FOR KEY IN ('height','length','width')
6 )
7 order by 1;
MSGID 'he 'le 'wi
---------- --- --- ---
15 18 19 20
16 21 22 23
17 24 25 26
SQL>

Related

How can this formula to swizzle rows be simplified?

The problem is quite simple to understand but solving it was not as easy as it sounded at first.
Let's assume the following, an image that is 8*4, normal order is easy, you return the pixel index:
// 00 01 02 03 04 05 06 07
// 08 09 10 11 12 13 14 15
// 16 17 18 19 20 21 22 23
// 24 25 26 27 28 29 30 31
Now suppose you want to swizzle rows like so:
// 00 01 02 03 04 05 06 07
// 16 17 18 19 20 21 22 23
// 08 09 10 11 12 13 14 15
// 24 25 26 27 28 29 30 31
I solved it, not without trouble to be honest, with the following formula:
index / 8 % 2 * 16 + index / 16 * 8 + index % 8
Isn't there a simpler formula to get the same result?
Assuming / and % return the quotient and remainder in the Euclidean division:
The classic ordering can be obtained as:
row = n / 8
col = n % 8
And the swizzled ordering can be obtained as:
col = n % 8
old_row = n / 8
new_row = 2 * (old_row / 2) + (1 - (old_row % 2))
Explanation:
2 * (old_row / 2) groups the rows two by two;
(1 - (old_row % 2)) swaps row 0 and row 1 of each group.

Oracle SQL Group By Hour for 24 hours

I have this query, which works:
SELECT TO_CHAR(last_date_called,'HH24'), count(*)
FROM log_table
GROUP BY TO_CHAR(last_date_called,'HH24');
But, in some cases there are not 24 hours worth of data. What I want to do, is always generate 24 rows, and if there is nothing for that hour, return 0. So, results may look like this:
00 10
01 25
02 33
03 0
04 55
05 0
06 23
And so on........
You'll need a row generator to create all hours in a day, and then outer join it to your "real" table. Something like this (see comments within code):
SQL> with
2 hours as
3 -- row generator, to create all hours in a day
4 (select lpad(level - 1, 2, '0') hour
5 from dual
6 connect by level <= 24
7 ),
8 log_table (last_date_called) as
9 -- sample data, just to return "something"
10 (select to_date('08.07.2021 13:32', 'dd.mm.yyyy hh24:mi') from dual union all
11 select to_date('16.02.2021 08:20', 'dd.mm.yyyy hh24:mi') from dual
12 )
13 -- final query
14 select h.hour,
15 count(l.last_date_called) cnt
16 from hours h left join log_table l on h.hour = to_char(l.last_date_called, 'hh24')
17 group by h.hour
18 order by h.hour;
HO CNT
-- ----------
00 0
01 0
02 0
03 0
04 0
05 0
06 0
07 0
08 1
09 0
10 0
11 0
12 0
13 1
14 0
15 0
16 0
17 0
18 0
19 0
20 0
21 0
22 0
23 0
24 rows selected.
SQL>

Power BI - Get last month from last year

I have this table:
Year
Month
Agency
Value
2019
9
1
233
2019
9
4
132
2019
8
3
342
2020
3
2
321
2020
3
4
34
2020
5
2
56
2020
5
4
221
2020
5
1
117
2018
12
2
112
2018
12
2
411
2020
4
3
241
2020
4
2
155
I'd like to set a new measure/column where last month from last year is 1, and 0 in another cases:
Year
Month
Agency
Value
Filter
2019
9
1
233
0
2019
9
4
132
0
2019
8
3
342
0
2020
3
2
321
0
2020
3
4
34
0
2020
5
2
56
1
2020
5
4
221
1
2020
5
1
117
1
2018
12
2
112
0
2018
12
2
411
0
2020
4
3
241
0
2020
4
2
155
0
I've been able to "copy" a new table with values from Month=5 and Year=2020 ("the lastest from the lastest"):
TableData - Last Charge =
var table = FILTER(
TableData,
AND(
MAX('TableData '[Year])='TableData '[Year],
MAX('TableData '[Month])='TableData '[Month]
)
)
return SUMMARIZE(table , TableData [Year], TableData [Month], TableData [Agency], TableData [Value])
However, my intention is don't create new tables and use measures/columns tu use it like FILTER when I create a graphic.
Thanks a lot, and sorry for my poor english.
I solved it with this measure:
Measure =
VAR a =
MAX ( 'Table'[Year] )
VAR b =
MAX ( 'Table'[Months] )
VAR c =
MAXX ( ALL ( 'Table' ), [Year] )
VAR d =
MAXX ( FILTER ( ALL ( 'Table' ), [Year] = c ), [Months] )
RETURN
IF ( a * 100 + b = c * 100 + d, 1, 0 )

Error returning when counting records in a query grouped in Oracle

I have a problem trying to group some records and trying to count the number of records returned by a query is adding an example:
07 COMERCIO 92
15 SERVICIOS OTROS 41
01 AGRICULTURA, GANADERIA Y SILVICULTURA 141
04 INDUSTRIA MANUFACTURERA 28
10 BANCA Y FINANZAS 5
12 ADMINISTRACION PUBLICA 16
03 MINERIA 3
16 HOGAR 2
08 HOTELES Y RESTAURANTES 37
11 EMPRESARIAL 21
14 SOCIAL Y SALUD 4
06 CONSTRUCCIÓN 3
09 TRANSPORTE 30
13 EDUCACION 10
This is query:
SELECT
AGRUP.VC_CODDET AS CHR_SECECO,
AGRUP.VC_NOMDET AS VC_SECECO,
0 AS INT_NROPRESTAMO,
COUNT(*) INTO_BENEFICIARIOS,
0 AS DEC_SALCON
FROM TB_JSI_PRESTAMO_DETALLE PREDET
INNER JOIN TB_JSI_PRESTAMO PRE ON
PRE.INT_IDPRESTAMO=PREDET.INT_IDPRESTAMO
INNER JOIN TB_JSI_BENEFICIARIO_IFI BENIFI ON
BENIFI.INT_IDBENEIFI=PRE.INT_IDBENEIFI
INNER JOIN TB_JSI_OPERACION OPE ON PRE.INT_IDOPE = OPE.INT_IDOPE AND
TRUNC(TO_DATE(OPE.DT_FECVEN))>TRUNC(TO_DATE('30/09/2018', 'DD/MM/YY'))
INNER JOIN TB_JSI_CIIU CIIU ON PRE.INT_IDACT = CIIU.INT_IDACT AND
PRE.INT_IDSEC=CIIU.INT_IDCLAS
INNER JOIN TB_JSI_TABLA_DET SECECO ON SECECO.INT_IDDET=CIIU.INT_IDCLAS
INNER JOIN TB_JSI_AGRUPA_SECTOR AGRSEC ON SECECO.INT_IDDET =
AGRSEC.INT_IDSEC
INNER JOIN TB_JSI_TABLA_DET AGRUP ON AGRSEC.INT_IDAGRU = AGRUP.INT_IDDET
INNER JOIN TB_JSI_TABLA_DET MON ON OPE.INT_IDMON = MON.INT_IDDET
INNER JOIN TB_JSI_IFI IFI ON OPE.INT_IDIFI = IFI.INT_IDIFI
WHERE TRUNC(PREDET.DTE_FECPRO) = (
SELECT
TRUNC(DTE_FECPRO)
FROM (SELECT
DTE_FECPRO
FROM TB_JSI_PRESTAMO_DETALLE
WHERE DTE_FECPRO<=TO_DATE('30/09/2018','DD/MM/YY')
AND DEC_SALDOL>0
ORDER BY DTE_FECPRO DESC)
WHERE ROWNUM = 1
)
AND (NULL IS NULL OR OPE.INT_IDTIPPRO =2)
AND (NULL IS NULL OR OPE.INT_IDMON = 364)
AND (NULL IS NULL OR OPE.INT_IDIFI=72)
GROUP BY AGRUP.VC_CODDET, AGRUP.VC_NOMDET
and should return this result
07 COMERCIO 92
15 SERVICIOS OTROS 41
01 AGRICULTURA, GANADERIA Y SILVICULTURA 141
04 INDUSTRIA MANUFACTURERA 28
10 BANCA Y FINANZAS 4
12 ADMINISTRACION PUBLICA 16
03 MINERIA 3
16 HOGAR 2
08 HOTELES Y RESTAURANTES 37
11 EMPRESARIAL 21
14 SOCIAL Y SALUD 4
06 CONSTRUCCIÓN 3
09 TRANSPORTE 30
13 EDUCACION 10
since I have these records and when counting I should return 4 and not 5
269516 10 BANCA Y FINANZAS 1
269558 10 BANCA Y FINANZAS 1
269592 10 BANCA Y FINANZAS 2
269611 10 BANCA Y FINANZAS 1
#Roller, I have analyzed the result and it is now clear that one of the tables used in the query has two records with the matching condition and that is why it is returning 5 and not 4.
You just need to identify the table and if you are not able to, then use the following trick.
First of all, identify the table, basis of which you are saying that there must be 4 rows and then use that table's PK in the count with distinct as follows:
COUNT(DISTINCT MY_PK)

Can i find out if a column is a primary key through Oracle ALL_TAB_COLS view?

Can i find out if a column is a primary or foreign key through Oracle's ALL_TAB_COLS view?
select *
from all_tab_cols
where table_name = 'ALL_TAB_COLS'
;
1 SYS ALL_TAB_COLS OWNER VARCHAR2 30 N 1 <Long> CHAR_CS 30 NO NO 30 B NO YES NO NO 1 1
2 SYS ALL_TAB_COLS TABLE_NAME VARCHAR2 30 N 2 <Long> CHAR_CS 30 NO NO 30 B NO YES NO NO 2 2
3 SYS ALL_TAB_COLS COLUMN_NAME VARCHAR2 30 N 3 <Long> CHAR_CS 30 NO NO 30 B NO YES NO NO 3 3
4 SYS ALL_TAB_COLS DATA_TYPE VARCHAR2 106 Y 4 <Long> CHAR_CS 106 NO NO 106 B NO YES NO NO 4 4
5 SYS ALL_TAB_COLS DATA_TYPE_MOD VARCHAR2 3 Y 5 <Long> CHAR_CS 3 NO NO 3 B NO YES NO NO 5 5
6 SYS ALL_TAB_COLS DATA_TYPE_OWNER VARCHAR2 30 Y 6 <Long> CHAR_CS 30 NO NO 30 B NO YES NO NO 6 6
7 SYS ALL_TAB_COLS DATA_LENGTH NUMBER 22 N 7 <Long> NO NO 0 NO YES NO NO 7 7
8 SYS ALL_TAB_COLS DATA_PRECISION NUMBER 22 Y 8 <Long> NO NO 0 NO YES NO NO 8 8
9 SYS ALL_TAB_COLS DATA_SCALE NUMBER 22 Y 9 <Long> NO NO 0 NO YES NO NO 9 9
10 SYS ALL_TAB_COLS NULLABLE VARCHAR2 1 Y 10 <Long> CHAR_CS 1 NO NO 1 B NO YES NO NO 10 10
11 SYS ALL_TAB_COLS COLUMN_ID NUMBER 22 Y 11 <Long> NO NO 0 NO YES NO NO 11 11
12 SYS ALL_TAB_COLS DEFAULT_LENGTH NUMBER 22 Y 12 <Long> NO NO 0 NO YES NO NO 12 12
13 SYS ALL_TAB_COLS DATA_DEFAULT LONG 0 Y 13 <Long> CHAR_CS 0 NO NO 0 NO YES NO NO 13 13
14 SYS ALL_TAB_COLS NUM_DISTINCT NUMBER 22 Y 14 <Long> NO NO 0 NO YES NO NO 14 14
15 SYS ALL_TAB_COLS LOW_VALUE RAW 32 Y 15 <Long> NO NO 0 NO YES NO NO 15 15
16 SYS ALL_TAB_COLS HIGH_VALUE RAW 32 Y 16 <Long> NO NO 0 NO YES NO NO 16 16
17 SYS ALL_TAB_COLS DENSITY NUMBER 22 Y 17 <Long> NO NO 0 NO YES NO NO 17 17
18 SYS ALL_TAB_COLS NUM_NULLS NUMBER 22 Y 18 <Long> NO NO 0 NO YES NO NO 18 18
19 SYS ALL_TAB_COLS NUM_BUCKETS NUMBER 22 Y 19 <Long> NO NO 0 NO YES NO NO 19 19
No - you can't since this information is not part of that view, see http://download.oracle.com/docs/cd/B13789_01/server.101/b10755/statviews_1179.htm
To find out the primary key column(s) of a table see http://www.techonthenet.com/oracle/questions/find_pkeys.php - the information is in the Views all_constraints + all_cons_columns .
To find foreign key information try:
SELECT cols.table_name, cols.column_name, cols.position, cons.status, cons.owner
FROM all_constraints cons, all_cons_columns cols
WHERE cons.constraint_type = 'R'
AND cons.constraint_name = cols.constraint_name
ORDER BY cols.table_name, cols.position;
The below query of Oracle DB, will list you all such table names present in your current schema which have the given column (YOUR_COLUMN_NAME) declared as primary key/composite key:
SELECT cols.table_name,
cols.column_name,
cols.position,
cons.status,
cons.owner
FROM all_constraints cons,
all_cons_columns cols
WHERE cons.constraint_type = 'P'
AND cols.column_name = '<GIVE_YOUR_COLUMN_NAME_HERE>'
AND cons.constraint_name = cols.constraint_name
AND cons.owner = cols.owner
ORDER BY cols.table_name,cols.position;
This is what I did to determine whether or not a column was part of a primary key (Assuming Primary keys have not been given fancy names):
select a.*, b.CONSTRAINT_NAME
from ALL_TAB_COLS a
left join
(select CONSTRAINT_NAME,table_name,column_name from ALL_CONS_COLUMNS
where OWNER= '<USER_YOU_WANT>'
and (CONSTRAINT_NAME like '%PK'
or CONSTRAINT_NAME like 'PK%'
or CONSTRAINT_NAME like '%PK%')
and CONSTRAINT_NAME not like 'BIN%') B on a.COLUMN_NAME=B.COLUMN_NAME and a.TABLE_NAME=B.TABLE_NAM
WHERE a.OWNER='<USER_YOU_WANT>'
;

Resources