Oracle impdp running way too long - oracle
I'm trying to import a schema into an oracle instance, that's running in a docker container (hopefully this is not relevant).
I would like to apologize in advance for the long post, but I wanted to include all I have already checked.
The import quickly loads the tables, builds the indexes, but when it gets to the packages progress just stops.
The log output stops with these lines
Processing object type SCHEMA_EXPORT/VIEW/COMMENT
Processing object type SCHEMA_EXPORT/PACKAGE/PACKAGE_BODY
It appears to be stuck in process 273, "ALTER PACKAGE ..."
set linesize 200
select s.username, s.sid, s.process, s.status, t.command_type, t.sql_text
from v$session s
, v$sqltext t
where t.sql_id = s.sql_id
order by t.sql_id, t.piece
USERNAME SID PROCESS STATUS COMMAND_TYPE SQL_TEXT
------------------------------ ---------- ------------------------ -------- ------------ ----------------------------------------------------------------
SYS 192 266 ACTIVE 47 BEGIN :1 := sys.kupc$que_int.get_status(:2, :3); END;
SYS 195 699 ACTIVE 3 select s.username, s.sid, s.process, s.status, t.command_type, t
SYS 195 699 ACTIVE 3 .sql_text from v$session s , v$sqltext t where t.sql_id
SYS 195 699 ACTIVE 3 = s.sql_id order by t.sql_id, t.piece
SYS 7 273 ACTIVE 98 ALTER PACKAGE "XXX"."XXX_AQ_PUT" COMPILE BODY PLSQL_OPTIM
SYS 7 273 ACTIVE 98 IZE_LEVEL= 2 PLSQL_CODE_TYPE= INTERPRETED PLSQL_DEBUG=
SYS 7 273 ACTIVE 98 FALSE PLSCOPE_SETTINGS= 'IDENTIFIERS:NONE' REUSE SETTINGS TI
SYS 7 273 ACTIVE 98 MESTAMP '2015-06-02 13:31:03'
SYS 196 271 ACTIVE 47 BEGIN :1 := sys.kupc$que_int.receive(:2); END;
but "ps agxu" reveals that process 273 uses a lot of CPU
oracle 119 0.0 0.0 1782464 14724 ? Ss 10:56 0:01 ora_pmon_xxxdb
oracle 121 0.0 0.0 1780172 11276 ? Ss 10:56 0:02 ora_vktm_xxxdb
oracle 125 0.0 0.0 1780172 11216 ? Ss 10:56 0:00 ora_gen0_xxxdb
oracle 127 0.0 0.0 1780172 11228 ? Ss 10:56 0:00 ora_diag_xxxdb
oracle 129 0.0 0.0 1780172 19120 ? Ss 10:56 0:00 ora_dbrm_xxxdb
oracle 131 0.0 0.0 1780172 11504 ? Ss 10:56 0:00 ora_psp0_xxxdb
oracle 133 0.0 0.0 1780684 14884 ? Ss 10:56 0:04 ora_dia0_xxxdb
oracle 135 0.0 0.3 1780172 109800 ? Ss 10:56 0:00 ora_mman_xxxdb
oracle 137 0.0 1.3 1817344 439448 ? Ss 10:56 0:02 ora_dbw0_xxxdb
oracle 139 0.0 0.0 1796924 20736 ? Ss 10:56 0:01 ora_lgwr_xxxdb
oracle 141 0.0 0.0 1780684 29472 ? Ss 10:56 0:02 ora_ckpt_xxxdb
oracle 143 0.0 0.3 1786832 108004 ? Ss 10:56 0:01 ora_smon_xxxdb
oracle 145 0.0 0.0 1781708 20928 ? Ss 10:56 0:00 ora_reco_xxxdb
oracle 147 0.0 0.1 1786180 62136 ? Ss 10:56 0:01 ora_mmon_xxxdb
oracle 149 0.0 0.0 1780172 19240 ? Ss 10:56 0:00 ora_mmnl_xxxdb
oracle 151 0.0 0.0 1803680 11540 ? Ss 10:56 0:00 ora_d000_xxxdb
oracle 153 0.0 0.0 1781368 10352 ? Ss 10:56 0:00 ora_s000_xxxdb
oracle 163 0.0 0.0 1780172 13140 ? Ss 10:56 0:00 ora_qmnc_xxxdb
oracle 228 0.0 0.0 9508 1288 ? S 10:56 0:00 /bin/bash /home/oracle/bin/import-dump
oracle 243 0.0 0.1 1784780 56672 ? Ss 10:56 0:01 ora_cjq0_xxxdb
oracle 263 0.0 0.0 1783616 25872 ? Ss 10:56 0:00 ora_q001_xxxdb
oracle 266 0.0 0.0 64128 12920 ? S 10:57 0:00 impdp as sysdba' directory=data dumpfile=xxx_exp.dmp schemas=xxx version=11.1
oracle 267 0.0 0.3 1796312 115144 ? Ss 10:57 0:04 oraclexxxdb (DESCRIPTION=(LOCAL=YES)(ADDRESS=(PROTOCOL=beq)))
oracle 269 0.0 0.0 1780916 15944 ? Ss 10:57 0:00 ora_q002_xxxdb
oracle 271 0.0 0.3 1828020 117032 ? Ss 10:57 0:04 ora_dm00_xxxdb
oracle 273 98.1 3.9 1981864 1293136 ? Rs 10:57 216:44 ora_dw00_xxxdb
oracle 275 0.0 0.0 1790988 20540 ? Ss 10:57 0:01 ora_smco_xxxdb
oracle 277 0.0 0.0 1790920 28676 ? Ss 10:57 0:01 ora_w000_xxxdb
There is plenty of free diskspace, and the tablespaces can expand as seen from this report
set linesize 150
set pagesize 50
col "Tablespace" for a25
col "Used MB" for 99,999
col "Free MB" for 99,999
col "Total MB" for 99,999
col "Max MB" for 99,999
select df.tablespace_name "Tablespace"
, totalusedspace "Used MB"
, (df.totalspace - tu.totalusedspace) "Free MB"
, df.totalspace "Total MB"
, round(100 * ( (df.totalspace - tu.totalusedspace)/ df.totalspace)) "Pct. Free"
, MaxSpace "Max MB"
from (
select tablespace_name
, round(sum(bytes) / 1048576) TotalSpace
, round(sum(
case
when maxbytes = 0 then bytes
else maxbytes
end
) / 1024 / 1024) MaxSpace
from dba_data_files
group by tablespace_name
) df,
(
select round(sum(bytes)/(1024*1024)) totalusedspace
, tablespace_name
from dba_segments
group by tablespace_name
) tu
where df.tablespace_name = tu.tablespace_nam
Tablespace Used MB Free MB Total MB Pct. Free Max MB
------------------------- ------- ------- -------- ---------- -------
SYSAUX 455 25 480 5 32,768
UNDOTBS1 127 3 130 2 32,768
XXX_T_256K 50 2 52 4 32,768
XXX_T_8M 858 43 901 5 32,768
XXX_T_256M 11,664 642 12,306 5 65,536
USERS 0 5 5 100 32,768
SYSTEM 684 6 690 1 32,768
XXX_I_8M 584 29 613 5 32,768
XXX_I_256K 5 1 6 17 32,768
XXX_I_256M 34,496 1,772 36,268 5 65,536
There are no blocking locks
set lines 200
set pages 50
col object1 for a30
col object2 for a30
select l.*, o1.owner || '.' || o1.object_name object1, o2.owner || '.' || o2.object_name object2
from v$lock l
, dba_objects o1
, dba_objects o2
where o1.object_id = l.id1
and o2.object_id(+) = l.id2
ADDR KADDR SID TY ID1 ID2 LMODE REQUEST CTIME BLOCK OBJECT1 OBJECT2
---------------- ---------------- ---------- -- ---------- ---------- ---------- ---------- ---------- ---------- ------------------------------ ------------------------------
00000000BFC51AC8 00000000BFC51B20 7 TO 12697 1 3 0 11738 0 SYS.IMPDP_STATS .
00000000BFC50F50 00000000BFC50FA8 3 RS 25 1 2 0 12155 0 SYS.PROXY_ROLE_DATA$ .
00000000BFC519E0 00000000BFC51A38 66 TS 3 1 3 0 12155 0 SYS.I_OBJ# .
00000000BFC51910 00000000BFC51968 127 MR 201 0 4 0 12155 0 SYS.I_SQL$TEXT_HANDLE .
00000000BFC510F0 00000000BFC51148 7 AE 100 0 4 0 12087 0 SYS.ORA$BASE .
00000000BFC51360 00000000BFC513B8 192 AE 100 0 4 0 12092 0 SYS.ORA$BASE .
00000000BFC51430 00000000BFC51488 190 AE 100 0 4 0 12154 0 SYS.ORA$BASE .
00000000BFC51B98 00000000BFC51BF0 196 AE 100 0 4 0 12090 0 SYS.ORA$BASE .
00000000BFC51C68 00000000BFC51CC0 195 AE 100 0 4 0 180 0 SYS.ORA$BASE .
00000000BFC527E0 00000000BFC52838 127 MR 11 0 4 0 12093 0 SYS.I_USER# .
00000000BFC50DB0 00000000BFC50E08 3 XR 4 0 1 0 12159 0 SYS.TAB$ .
00000000BFC51840 00000000BFC51898 127 MR 4 0 4 0 12155 0 SYS.TAB$ .
00000000BFC516A0 00000000BFC516F8 127 MR 2 0 4 0 12155 0 SYS.C_OBJ# .
00000000BFC528B0 00000000BFC52908 127 MR 12 0 4 0 12093 0 SYS.FET$ .
00000000BFC52628 00000000BFC52680 127 MR 10 0 4 0 12093 0 SYS.C_USER# .
00000000BFC52558 00000000BFC525B0 127 MR 8 0 4 0 12093 0 SYS.C_FILE#_BLOCK# .
00000000BFC52218 00000000BFC52270 127 MR 5 0 4 0 12093 0 SYS.CLU$ .
00000000BFC522E8 00000000BFC52340 127 MR 6 0 4 0 12093 0 SYS.C_TS# .
00000000BFC52488 00000000BFC524E0 127 MR 7 0 4 0 12093 0 SYS.I_TS# .
00000000BFC523B8 00000000BFC52410 127 MR 9 0 4 0 12093 0 SYS.I_FILE#_BLOCK# .
00000000BFC51770 00000000BFC517C8 127 MR 3 0 4 0 12155 0 SYS.I_OBJ# .
Update:
Unfortunately I still can't see what's wrong.
The select from gv$session gave no rows.
Here is an excerpt of the output from gv$sql. It's sorted on last_load_time, so it should show a timeline of what has been going on. The ALTER PACKAGE is still marked active, but has only used 182 microseconds in three days, and as far as I can see there are no recursive SQL statements, the ALTER could be waiting on.
SQL> select elapsed_time/1000000 seconds, s.inst_id, s.sql_text, s.users_executing, s.cpu_time,
s.first_load_time, s.last_load_time
2 3 from gv$sql s
4 where users_executing > 0
5 union
select elapsed_time/1000000 seconds, s.inst_id, s.sql_text, s.users_executing, s.cpu_time,
s.first_load_time, s.last_load_time
6 7 8 from gv$sql s
9 where rownum < 50
10 order by last_load_time
11 /
SECONDS INST_ID SQL_TEXT USERS_EXECUTING CPU_TIME FIRST_LOAD_TIME LAST_LOAD_TIME
---------- ---------- -------------------------------------------------- --------------- ---------- ------------------- -------------------
.000293 1 LOCK TABLE FOR INDEX "XXX"."PK_YYYYYYYYYYYYYYYYYY 0 572 2016-04-08/11:02:09 2016-04-08/11:02:09
" IN EXCLUSIVE MODE NOWAIT
.000358 1 LOCK TABLE FOR INDEX "XXX"."IX_XXX_YYYYYYYYYYYYYY 0 2132 2016-04-08/11:02:38 2016-04-08/11:02:38
YYYYY" IN EXCLUSIVE MODE NOWAIT
.000349 1 LOCK TABLE FOR INDEX "XXX"."IX_XXX_DATA_02" IN EX 0 574 2016-04-08/11:03:06 2016-04-08/11:03:06
CLUSIVE MODE NOWAIT
.000402 1 INSERT INTO "SYS". "IMPDP_STATS" (TYPE,VERSION,FLA 0 289 2016-04-08/11:03:17 2016-04-08/11:03:17
GS,C1,C2,C3,C5,N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11,
N12,D1,CL1) VALUES ('I',5,2,:B3 ,NULL,NULL,:B2 ,15
219,31,15219,1,1,2108,1,15219,NULL,NULL,NULL,NULL,
TO_DATE('2014-11-15 19:10:36',:B1 ),NULL)
.000405 1 INSERT INTO "SYS". "IMPDP_STATS" (TYPE,VERSION,FLA 0 0 2016-04-08/11:03:17 2016-04-08/11:03:17
GS,C1,C2,C3,C5,N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11,
N12,D1,CL1) VALUES ('I',5,2,:B3 ,NULL,NULL,:B2 ,10
6867,670,713,1,6,4759,2,106867,NULL,NULL,NULL,NULL
,TO_DATE('2016-03-19 19:19:38',:B1 ),NULL)
.000419 1 INSERT INTO "SYS". "IMPDP_STATS" (TYPE,VERSION,FLA 0 743 2016-04-08/11:03:17 2016-04-08/11:03:17
GS,C1,C2,C3,C5,N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11,
N12,D1,CL1) VALUES ('I',5,2,:B3 ,NULL,NULL,:B2 ,13
7849,1763,11,160,686,7556,2,137849,NULL,NULL,NULL,
NULL,TO_DATE('2016-02-20 19:20:18',:B1 ),NULL)
.000425 1 INSERT INTO "SYS". "IMPDP_STATS" (TYPE,VERSION,FLA 0 0 2016-04-08/11:03:17 2016-04-08/11:03:17
GS,C1,C2,C3,C5,N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11,
N12,D1,CL1) VALUES ('I',5,2,:B3 ,NULL,NULL,:B2 ,70
9979,2005,3,668,18908,56726,2,709979,NULL,NULL,NUL
L,NULL,TO_DATE('2016-03-26 19:19:30',:B1 ),NULL)
.000451 1 INSERT INTO "SYS". "IMPDP_STATS" (TYPE,VERSION,FLA 0 280 2016-04-08/11:03:17 2016-04-08/11:03:17
GS,C1,C2,C3,C5,N1,N2,N3,N4,N5,N6,N7,N8,N9,N10,N11,
N12,D1,CL1) VALUES ('I',5,2,:B3 ,NULL,NULL,:B2 ,0,
0,0,0,0,0,0,0,NULL,NULL,NULL,NULL,TO_DATE('2016-02
-20 19:20:18',:B1 ),NULL)
.001567 1 delete from viewtrcol$ where obj#=:1 0 1405 2016-04-08/10:57:24 2016-04-08/11:03:18
.000182 1 ALTER PACKAGE "XXX"."XXX_AQ_PUT" COMPILE BODY 1 372 2016-04-08/11:03:25 2016-04-08/11:03:25
PLSQL_OPTIMIZE_LEVEL= 2 PLSQL_CODE_TYPE= I
NTERPRETED PLSQL_DEBUG= FALSE PLSCOPE_SETTI
NGS= 'IDENTIFIERS:NONE' REUSE SETTINGS TIMESTAMP
'2015-06-02 13:31:03'
.003691 1 insert into wrh$_filemetric_history (snap_id, 0 2914 2016-04-08/11:06:36 2016-04-08/11:06:36
dbid, instance_number, fileid, creationtime,
begin_time, end_time, intsize, group_id,
avgreadtime, avgwritetime, physicalread, phy
sicalwrite, phyblkread, phyblkwrite) select
:snap_id, :dbid, :instance_number, fileid, cr
eationtime, begtime, endtime, intsize_csec, g
roupid, avrdtime, avwrtime, phyread, phy
write, phybkrd, phybkwr from x$kewmflmv
.004734 1 INSERT INTO WRH$_METRIC_NAME(dbid, GROUP_ID, METRI 0 2384 2016-04-08/11:06:36 2016-04-08/11:06:36
C_ID, GROUP_NAME, METRIC_NAME, METRIC_UNIT) SELECT
DISTINCT :dbid, GROUP_ID, METRIC_ID, GROUP_NAME,
METRIC_NAME, METRIC_UNIT FROM V$METRICNAME
.009059 1 SELECT COUNT(*) FROM (SELECT TOP_LEVEL_CALL#, TOP_ 0 4325 2016-04-08/11:06:36 2016-04-08/11:06:36
LEVEL_CALL_NAME FROM V$TOPLEVELCALL MINUS SELECT T
OP_LEVEL_CALL#, TOP_LEVEL_CALL_NAME FROM WRH$_TOPL
EVELCALL_NAME WHERE dbid = :dbid)
.003014 1 delete from WRH$_ENQUEUE_STAT tab where (:beg_snap 0 2124 2016-04-08/11:26:19 2016-04-08/11:26:19
<= tab.snap_id and tab.snap_id <= :end_sn
ap and dbid = :dbid) and not exists (se
lect 1 from WRM$_BASELINE b whe
re (tab.dbid = b.dbid) and
(tab.snap_id >= b.start_snap_id) and
(tab.snap_id <= b.end_snap_id))
Not much to see en dba_resumables too
1* select * from dba_resumable
USER_ID SESSION_ID INSTANCE_ID COORD_INSTANCE_ID COORD_SESSION_ID STATUS TIMEOUT START_TIME SUSPEND_TIME RESUME_TIME NAME SQL_TEXT ERROR_NUMBER ERROR_PARAMETER1 ERROR_PARAMETER2 ERROR_PARAMETER3 ERROR_PARAMETER4 ERROR_PARAMETER5 ERROR_MSG
---------- ---------- ----------- ----------------- ---------------- --------- ---------- -------------------- -------------------- -------------------- ------------------------------ -------------------------------------------------- ------------ -------------------- -------------------- -------------------- -------------------- -------------------- --------------------------------------------------
0 196 1 NORMAL 7200 SYS.SYS_IMPORT_SCHEMA_01 BEGIN :1 := sys.kupc$que_int.receive(:2); END; 0
0 7 1 NORMAL 7200 SYS.SYS_IMPORT_SCHEMA_01.1 ALTER PACKAGE "XXX"."XXX_AQ_PUT" COMPILE BODY 0
PLSQL_OPTIMIZE_LEVEL= 2 PLSQL_CODE_TYPE= I
NTERPRETED PLSQL_DEBUG= FALSE PLSCOPE_SETTI
NGS= 'IDENTIFIERS:NONE' REUSE SETTINGS TIMESTAMP
'2015-06-02 13:31:03'
I feel stuck :-(
The simplest way to find blocking locks is to look at the sessions. It's usually best to look for who is blocking, not what is blocking.
select *
from gv$session
where blocking_session is not null
The ALTER may be waiting on a recursive SQL statement. Those statement do not always count as "blocking". Run this statement to see what other SQL is running. If you're lucky there will be a statement that has been running almost as long as the ALTER; that will be the next query to investigate:
select elapsed_time/1000000 seconds, gv$sql.*
from gv$sql
where users_executing > 0
order by users_executing desc;
For investigating space issues it is usually better to look at DBA_RESUMABLE instead of specific space sizes. There are a lot of ways for Oracle to run out of space. The tablespace may look fine, but ASM or the OS may be out of space.
select * from dba_resumable;
Based on the updates it looks like the imported data contains Advanced Queues objects. Advanced Queue's have additional import and export restrictions. Everything is "special" with AQ's. Hopefully your organization has someone who specializes in AQs. It wouldn't surprise me if you'll need a create a Support Request for this issue.
The answer most likely lies in the output of your query on v$sql .. specifically the INSERT INTO "SYS". "IMPDP_STATS"
You will notice little use of bind variables ... this code is transferring statistics from the source database one object at a time hardcoding most of the values .. even though this is code written by Oracle's own developers.
The solution is to not export statistics during expdp - e.g. EXCLUDE=STATISTICS in the expdp parfile.
You can gather statistics anew after the import is complete - which has the advantage of ensuring up to date statistics. Alternatively, you could export statistics to tables prior to expdp and impp
Related
Oracle 11g - Insert Into Select / Insert and update (dbfiddle example inside)
I discover few time ago and really love dbfiddle, so I made my question with example made with this wonderfull tool :-) I've a table in my Oracle Database. see the dbfiddle https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=2fa4b3440c660f5bba06120c07d48071 I've to add in this table thanks to this query : INSERT INTO STATS_CLIENT_TEST (CODECLIENT, CODEAXESTAT, CODEELEMENTSTAT, VALEURAXESTATISTIQUECLIENT) SELECT CODECLIENT, 174, 0, 1 FROM STATS_CLIENT_TEST where VALEURAXESTATISTIQUECLIENT='2021' 1000 174 0 1 1000 174 0 1 1002 174 0 1 1003 174 0 1 It's work but, I would like to get the final result here (last): https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=e09d1b7c221bfc2259e36590379cbd05 1000 174 0 2 1002 174 0 1 1003 174 0 1 How could I have the result I try to get ? Thank you :-)
Use the following query in your INSERT INTO statement: SELECT CODECLIENT, 174, 0, COUNT(*) FROM STATS_CLIENT_TEST where VALEURAXESTATISTIQUECLIENT='2021' GROUP BY CODECLIENT db<>fiddle here
Retrieving profiles from a table based on specific logic
I have a requirement to extract profiles from a table for the below criteria: There are 5 IDs in total. 100, 200, 300, 400 and 500 The profiles to have atleast one ID of each value 100, 300 and 400. IDs with value 200 and 500 should not be present even once. Profile can have multiple number of IDs of value 300 and 400 but will have only one ID of value 100. The profiles will have IDs 300 and 400 equally. i.e For every ID will the value 300, there will be an ID of value 400. Eg: TABLE A: ------------------------- PROFILE_ID ID ------------------------- 12345 100 12345 300 12345 400 23456 100 23456 300 23456 400 23456 300 23456 400 34567 100 34567 200 ------------------------- The result should fetch PROFILE_IDs 12345 and 23456 and not 34567. I am pretty stuck and blank in getting a clear idea on how to frame a query for this. Please help.
For sample data you posted: SQL> select * From test; PROFILE_ID ID ---------- ---------- 12345 100 12345 300 12345 400 23456 100 23456 300 23456 400 23456 300 23456 400 34567 100 34567 200 10 rows selected. one option is to do it rule-by-rule, each of CTEs retrieving data which satisfy certain rule. The final result is intersection of these PROFILE_IDs. SQL> with 2 rule2 as -- don't allow IDs 200 nor 500 3 (select profile_id 4 from test 5 where profile_id not in (select profile_id 6 from test 7 where id in (200, 500) 8 ) 9 ), 10 rule3 as -- there can be only one ID = 100 for each PROFILE_ID 11 (select profile_id 12 from (select profile_id, 13 sum(case when id = 100 then 1 else 0 end) cnt_100 14 from test 15 group by profile_id 16 ) 17 where cnt_100 = 1 18 ), 19 rule4 as -- number of IDs 300 and 400 has to be equal and greater than 0 20 (select profile_id 21 from (select profile_id, 22 sum(case when id = 300 then 1 else 0 end) cnt_300, 23 sum(case when id = 400 then 1 else 0 end) cnt_400 24 from test 25 group by profile_id 26 ) 27 where cnt_300 = cnt_400 28 and cnt_300 > 0 29 ) 30 select profile_id from rule2 31 intersect 32 select profile_id from rule3 33 intersect 34 select profile_id from rule4; PROFILE_ID ---------- 12345 23456 SQL>
Personally, since all your rules rely on counting the different ids, I'd do it more like this. Some of this is redundant, but it makes explicit which part comes from which of your criteria. with rules as ( select profile_id, sum(case when id = 100 then 1 else 0 end) as cnt_100, sum(case when id = 200 then 1 else 0 end) as cnt_200, sum(case when id = 300 then 1 else 0 end) as cnt_300, sum(case when id = 400 then 1 else 0 end) as cnt_400, sum(case when id = 500 then 1 else 0 end) as cnt_500 from table1 group by profile_id ) select profile_id from rules -- rule 1 where cnt_100 > 0 and cnt_300 > 0 and cnt_400 > 0 -- rule 2 and cnt_200 = 0 and cnt_500 = 0 -- rule 3 and cnt_100 = 1 -- rule 4 and cnt_300 = cnt_400 SQL Fiddle
Pass parameters to oracle plsql function
I have written two queries. query 1: select stock_id from_id, nvl(lead(stock_id, 1, null) over (order by stock_date),stock_id) to_id from STOCK where stock_time not like 'NEW_STOCK'; The above query returns result like below: FROM_ID TO_ID 331 341 341 351 351 361 361 371 371 391 391 401 401 421 421 441 441 451 451 461 461 321 321 323 323 491 491 501 501 501 My second query is select max(m.material_thikness) || ' mm' || ' | ' || m.material_guage || ' g' guage, sum(util.find_usage_from_stock(MATERIAL_THIKNESS,P_FROM_ID,P_TO_ID)) - sum(util.find_sheets_sold(MATERIAL_THIKNESS,P_FROM_ID,P_TO_ID)) diff from material m where m.active like 'Y' group by m.material_guage order by m.material_guage; The above query returns results like below: GUAGE DIFF 6 mm | 11 g 0 4 mm | 12 g -0.32 3 mm | 13 g 0.51 2 mm | 14 g 0.85 1.5 mm | 16 g -0.41 1.2 mm | 18 g 0.35 1 mm | 19 g 1.67 .8 mm | 20 g 0 I need to add FROM_ID and TO_ID return from my first query into P_FROM_ID and P_TO_ID in my second query and I need to modify my second query to get results like below. RANGE DIFF 331-341 0 341-351 0.35 351-361 0.45 ....... 441-451 1.25 451-461 -0.75 461-321 1.67 How could I do that ?
If you want to get values for every material_thikness for all the p_id intervals then: select s.from_id || '-' ||s.to_id range, sum(util.find_usage_from_stock(MATERIAL_THIKNESS,s.from_id,s.to_id)) - sum(util.find_sheets_sold(MATERIAL_THIKNESS,s.from_id,s.to_id)) diff from material m, (select stock_id from_id, lead(stock_id, 1, stock_id) over (order by stock_date) to_id from STOCK where stock_time not like 'NEW_STOCK') s where m.active like 'Y' group by s.from_id,s.to_id order by s.from_id;
Are you looking for something like this: select max(m.material_thikness) || ' mm' || ' | ' || m.material_guage || ' g' guage, sum(util.find_usage_from_stock(MATERIAL_THIKNESS,P_FROM_ID,P_TO_ID)) - sum(util.find_sheets_sold(MATERIAL_THIKNESS,P_FROM_ID,P_TO_ID)) diff from material m where m.active like 'Y' and (m.p_from_id,m.p_to_id) in(select stock_id from_id, nvl(lead(stock_id, 1, null) over (order by stock_date),stock_id) to_id from STOCK where stock_time not like 'NEW_STOCK') group by m.material_guage order by m.material_guage; Will that do it?
PLSQL : need help to understand a CASE instructions in a ORDER BY
I have a piece of code that had a ORDER BY with a CASE in it: ORDER BY ( CASE WHEN r.id BETWEEN 900 AND 999 THEN '1AAAAA' ELSE '2' || upper(id.name) END) ASC, r.date DESC ; Could someone explain: what is the meaning of the '1AAAAA' and '2' ? what is the meaning of || upper(id.name)
In PL/SQL, || is the concatenation operator. Exactly how the ordering is happening depends on the rest of the query, but it looks like it's putting records with r.id BETWEEN 900 AND 999 before other records, which are sorted by id.name.
The case expression evaluates to a value CASE WHEN r.id BETWEEN 900 AND 999 THEN '1AAAAA' ELSE '2' || upper(id.name) END The whole above block of code with either evaluate to '1AAAAA', or '2[value-of-r.id]' depending on the value of r.id. As this is in the order by clause this value will be used to sort the results as follows: first list all records where r.id is between 900 and 999 then list all other records in ascending order of r.id (the || is the string concatenation operator).
Here is some data. As you can see the name sorts in ASCII order, which is not exactly the same as alphabetical order: SQL> select id, name, somedate 2 from t42 3 order by name, somedate 4 / ID NAME SOMEDATE ---------- ---------- --------- 8 Billington 24-MAR-11 13 Cave 19-MAR-11 4 Clarke 28-MAR-11 919 Feuerstein 13-MAR-11 16 Gasparotto 16-MAR-11 1014 KULASH 18-MAR-11 1 Kestelyn 31-MAR-11 917 Kishore 15-MAR-11 2 Lira 30-MAR-11 6 PADFIELD 26-MAR-11 11 Rigby 21-MAR-11 1007 Robertson 25-MAR-11 12 SCHNEIDER 20-MAR-11 9 SPENCER 23-MAR-11 3 TRICHLER 29-MAR-11 918 VERREYNNE 14-MAR-11 10 boehmer 22-MAR-11 15 hall 17-MAR-11 920 poder 12-MAR-11 5 van wijk 27-MAR-11 1021 11-MAR-11 21 rows selected. SQL> Sorting by upper(name) makes it case-insensitive: SQL> select id, name, somedate 2 from t42 3 order by upper(name), somedate 4 / ID NAME SOMEDATE ---------- ---------- --------- 8 Billington 24-MAR-11 10 boehmer 22-MAR-11 13 Cave 19-MAR-11 4 Clarke 28-MAR-11 919 Feuerstein 13-MAR-11 16 Gasparotto 16-MAR-11 15 hall 17-MAR-11 1 Kestelyn 31-MAR-11 917 Kishore 15-MAR-11 1014 KULASH 18-MAR-11 2 Lira 30-MAR-11 6 PADFIELD 26-MAR-11 920 poder 12-MAR-11 11 Rigby 21-MAR-11 1007 Robertson 25-MAR-11 12 SCHNEIDER 20-MAR-11 9 SPENCER 23-MAR-11 3 TRICHLER 29-MAR-11 5 van wijk 27-MAR-11 918 VERREYNNE 14-MAR-11 1021 11-MAR-11 21 rows selected. SQL> The CASE() changes this further by grouping all the records within the specfied ID range first, then all the other records. The records in the selected range are just sorted by the DATE whereas the other records are still sorted by name then date: SQL> select id, name, somedate 2 from t42 3 ORDER BY 4 ( 5 CASE 6 WHEN id BETWEEN 900 AND 999 THEN '1AAAAA' 7 ELSE '2' 8 || upper(name) 9 END) ASC, 10 somedate DESC 11 / ID NAME SOMEDATE ---------- ---------- --------- 917 Kishore 15-MAR-11 918 VERREYNNE 14-MAR-11 919 Feuerstein 13-MAR-11 920 poder 12-MAR-11 1021 11-MAR-11 8 Billington 24-MAR-11 10 boehmer 22-MAR-11 13 Cave 19-MAR-11 4 Clarke 28-MAR-11 16 Gasparotto 16-MAR-11 15 hall 17-MAR-11 1 Kestelyn 31-MAR-11 1014 KULASH 18-MAR-11 2 Lira 30-MAR-11 6 PADFIELD 26-MAR-11 11 Rigby 21-MAR-11 1007 Robertson 25-MAR-11 12 SCHNEIDER 20-MAR-11 9 SPENCER 23-MAR-11 3 TRICHLER 29-MAR-11 5 van wijk 27-MAR-11 21 rows selected. SQL>
1. what is the meaning of the '1AAAAA' and '2' ? That are literal constants. 2. what is the meaning of || upper(id.name) || is the SQL standard concatenation operator. 'A' || 'B' produces 'AB'. IMHO, your question is what the entire order by case means, so, go step by step: ORDER BY ( CASE WHEN r.id BETWEEN 900 AND 999 THEN '1AAAAA' ELSE '2' || upper(id.name) END) ASC, r.date DESC ; This will order your result set by the result of the case expression evaluation (ascendant), then by r.date (descendant). The case will just return '1AAAAA' for any ID between 900 and 999 (this will then be ordered by r.date, remember?' For any other value, it will concatenate 2 before the id.name. This ensures any record with id between 900 and 999 to appear in the first "group", which is ordered just by date, descending. Then a second group will contain all the other records, ordered by the upper of name, then by the date. You may want to see this data to understand how this works... just add the case expression to your select statement as a new column. For example if your query starts like this: SELECT r.id, id.name FROM add the case like this: SELECT r.id, id.name , CASE WHEN r.id BETWEEN 900 AND 999 THEN '1AAAAA' ELSE '2'|| upper(id.name) END ORDER_CRITERIA FROM This will help you understand what's going on with that expression, as you will see the produced data as the last column of your query.
Retrieve data in group based on the Value of other column
I have one table with the following Column. BoxNumber Status 580 4 581 4 582 4 583 4 584 2 585 2 586 4 587 4 588 4 589 4 590 2 591 2 I need one select Query to get the following output . StartingBoxNumber EndingBoxNumber Status 580 583 4 584 585 2 586 589 4 590 591 2
You can get the result with a single scan of the table, using analytics to define "groups" of contiguous rows: SQL> SELECT MIN(boxnumber), MAX(boxnumber), status 2 FROM (SELECT boxnumber, status, 3 SUM(status_change) over(ORDER BY boxnumber) group_id 4 FROM (SELECT boxnumber, status, 5 CASE 6 WHEN lag(status) over(ORDER BY boxnumber) 7 = status 8 AND lag(boxnumber) over(ORDER BY boxnumber) 9 = boxnumber - 1 THEN 10 0 11 ELSE 12 1 13 END status_change 14 FROM box)) 15 GROUP BY status, group_id 16 ORDER BY 1; MIN(BOXNUMBER) MAX(BOXNUMBER) STATUS -------------- -------------- ---------- 580 583 4 584 585 2 586 589 4 590 591 2
Assuming box numbers are always consecutive: SELECT COALESCE( LAG(Boxnumber) OVER (ORDER BY BoxNumber), ( SELECT MIN(BoxNumber) FROM mytable )) AS StartBoxNumber, BoxNumber AS EndBoxNumber, status FROM mytable qo WHERE NOT EXISTS ( SELECT NULL FROM mytable qi WHERE qi.boxnumber = qo.boxnumber + 1 AND qi.status = qo.status )