Get managers first from table and employees later - oracle

I have a table like this
NAME -- MANAGER
10 -- 85
85 -- 45
45 -- 52
52 -- null
I want an output like this, where manager is put first in an hierarchy and then the employees
NAME -- MANAGER
52 -- null
45 -- 52
85 -- 45
10 -- 85
Can anyone help me do it. I did inner join like below, but it didn't work
select * from TABLEMAIN
inner join TABLEMAIN t2 ON TABLEMAIN.MANAGER = t2.NAME
order by TABLEMAIN.NAME
Please help me arrive at a solution

Can be achieved using start with and connect by
WITH TABLEMAIN(NAME,MANAGER) AS
(SELECT 10 ,85 FROM dual UNION ALL
SELECT 85 , 45 FROM dual UNION ALL
SELECT 45 ,52 FROM dual UNION ALL
SELECT 52 ,null FROM dual )
----
-- End of data
----
SELECT * FROM TABLEMAIN
START WITH manager IS NULL
CONNECT BY PRIOR NAME = manager
Output:
NAME MANAGER
52
45 52
85 45
10 85

Related

How to find text fields that contains a list of words

I'm using Oracle PLSQL.
I want to return TextFields that contains a list of words (with 'and' operator between them).
The result string must contain all the words provided from the user, the order is not importent.
Example:
param_col varchar2(100):= 'Project|Data|Book';
(The list of words are unknown, depend on user parameter)
TextField:
1.'The Project will contain Data from Book'
2.'The Project Data is not valid.
3.'Project is the best data Book exists'
Expected Result:
1.'The Project will contain Data from Book'
3.'Project is the best data Book exists'
Here's one option. See comments within code.
SQL> with
2 test (id, col) as
3 -- Test sample data
4 (select 1, 'The Project will contain Data from Book' from dual union all
5 select 2, 'The Project Data is not valid' from dual union all
6 select 3, 'Project is the best data Book exists' from dual
7 ),
8 param (par) as
9 -- input parameter
10 (select 'Project|Data|Book' from dual),
11 --
12 spltest as
13 -- split TEST sentences to words
14 (select id,
15 lower(regexp_substr(col, '[^ ]+', 1, column_value)) val
16 from test cross join table(cast(multiset(select level from dual
17 connect by level <= regexp_count(col, ' ') + 1
18 ) as sys.odcinumberlist))
19 ),
20 splpar as
21 -- split PARAMETER into words; include IDs from TEST
22 (select t.id,
23 lower(regexp_substr(p.par, '[^\|]+', 1, column_value)) val
24 from param p cross join test t
25 cross join table(cast(multiset(select level from dual
26 connect by level <= regexp_count(p.par, '\|') + 1
27 ) as sys.odcinumberlist))
28 )
29 -- final result: select rows from the TEST table ...
30 select t.id, t.col
31 from test t
32 -- ... where ID is contained in intersected set of values from SPLTEST and SPLPAR ...
33 where t.id in (select x.id from (select t1.id, t1.val from spltest t1
34 intersect
35 select p.id, p.val from splpar p
36 ) x
37 group by x.id
38 -- ... while that "intersected set" has to contain all values from the PARAM
39 having count(*) = (select regexp_count(p1.par, '\|') + 1
40 from param p1
41 )
42 );
ID COL
---------- ---------------------------------------
1 The Project will contain Data from Book
3 Project is the best data Book exists
SQL>

To display student id and the minimum mark scored by that students in any subject.Give an alias as minimum_mark. Sort the result based on minimum_mark

data in mark table:
VALUE SUBJECT_ID STUDENT_ID
---------- ---------- ----------
73 1 6
98 1 1
68 2 1
75 3 6
78 5 6
75 1 7
69 4 7
I have tried the following code, it executes successfully and gives the desired result, however it fails to clear one test case and IDK why?
SELECT DISTINCT
student_id,
min(value) as MINIMUM_MARK
FROM mark
WHERE value IN (
SELECT
min(value)
FROM mark
GROUP BY (subject_id)
)
GROUP BY (student_id)
ORDER BY MINIMUM_MARK;
The expected output is :
STUDENT_ID MINIMUM_MARK
---------- ------------
1 68
7 69
6 73
You can simply use group by as following:
Select student_id,
Min(value) as minimum_marks
From marks
Group by student_id
Order by minimum_marks
Cheers!!
I would just use ROW_NUMBER here:
WITH cte AS (
SELECT m.*, ROW_NUMBER() OVER (PARTITION BY STUDENT_ID ORDER BY "VALUE" DESC) rn
FROM mark
)
SELECT STUDENT_ID, MARK
FROM cte
WHERE rn = 1
ORDER BY MARK;

hive - inserting rows for different column value

Honestly, I don't know how simply I can describe the question on the title line instead of showing an example.
I have a hive table which contains two columns: ID and date
ID Date
31 01-01-2017
31 01-02-2017
31 01-03-2017
123 01-01-2017
123 01-01-2017
...
In this table, I would like to include another column which is hour such as below
ID Date Hour
31 01-01-2017 00
31 01-01-2017 01
31 01-01-2017 02
31 01-01-2017 03
31 01-01-2017 04
...
31 01-01-2017 23
31 01-02-2017 00
31 01-02-2017 01
...
Basically, for every row, I would like add an hour column of values from 00 to 23.
Can this be achieved using hive?
Thank you so much.
You could create a temporary table which contains entries from 0 to 23 and do a cross join with the table you have. Or you can leverage on the CTE function a CTE table with entries from 0 to 23 and then do a cross join with it.
An example:
with temp as (
select 0 hour union all
select 1 hour union all
select 2 hour union all
select 3 hour union all
select 4 hour union all
select 5 hour union all
select 6 hour union all
select 7 hour union all
select 8 hour union all
select 9 hour union all
select 10 hour union all
select 11 hour union all
select 12 hour union all
select 13 hour union all
select 14 hour union all
select 15 hour union all
select 16 hour union all
select 17 hour union all
select 18 hour union all
select 19 hour union all
select 20 hour union all
select 21 hour union all
select 22 hour union all
select 23 hour
)
select * from table join temp
You can also insert the result into a table to persist the result. Hope it helps

How to get one query about sales set on default date?

I have two tables, T_TEST and T_DEFAULT_DATE. T_TEST contains date and amount, and T_DEFAULT_DATE contains just P_DATE.
First table T_TEST:
DATE AMOUNT
-------- ----------
01.01.99 77
16.02.99 59
01.01.00 12
15.01.00 32
01.02.00 144
15.02.00 320
16.02.00 521
01.03.00 98
15.03.00 76
16.03.00 33
01.01.01 65
15.01.01 78
01.02.01 95
15.02.01 39
16.02.01 97
02.02.02 63
07.03.02 75
And second table T_DEFAULT_DATE:
P_DATE
--------
16.02.01
What I want to get is two queries established in a single query :
1. what is the amount of sale achieved on the same day last year (- 12 mounths)
2. amount of sales for whole past year (based on table T_DEFAULT_DATE)
3. the amount (sum) for whole mounth (default mounth : 1.2. 2001 - 28.2.2001)
Expected output is :
P_SDLY P_LY P_MS
-----------
521 1236 231
I tryed with add_months(t_default_date.p_date, -12) , but I didn't get expected result. Please help
You can try something like this, assuming that your fields are stored in date columns.
SQL> with t_test(date_, amount) as
2 (
3 select to_date('01.01.99', 'dd.mm.rr'), 77 from dual union all
4 select to_date('16.02.99', 'dd.mm.rr'), 59 from dual union all
5 select to_date('01.01.00', 'dd.mm.rr'), 12 from dual union all
6 select to_date('15.01.00', 'dd.mm.rr'), 32 from dual union all
7 select to_date('01.02.00', 'dd.mm.rr'), 144 from dual union all
8 select to_date('15.02.00', 'dd.mm.rr'), 320 from dual union all
9 select to_date('16.02.00', 'dd.mm.rr'), 521 from dual union all
10 select to_date('01.03.00', 'dd.mm.rr'), 98 from dual union all
11 select to_date('15.03.00', 'dd.mm.rr'), 76 from dual union all
12 select to_date('16.03.00', 'dd.mm.rr'), 33 from dual union all
13 select to_date('01.01.01', 'dd.mm.rr'), 65 from dual union all
14 select to_date('15.01.01', 'dd.mm.rr'), 78 from dual union all
15 select to_date('01.02.01', 'dd.mm.rr'), 95 from dual union all
16 select to_date('15.02.01', 'dd.mm.rr'), 39 from dual union all
17 select to_date('16.02.01', 'dd.mm.rr'), 97 from dual union all
18 select to_date('02.02.02', 'dd.mm.rr'), 63 from dual union all
19 select to_date('07.03.02', 'dd.mm.rr'), 75 from dual
20 ),
21 t_default_date(p_date) as
22 (
23 select to_date('16.02.01', 'dd.mm.rr') from dual
24 )
25 select sum(
26 case
27 when date_ between add_months(trunc(p_date, 'yyyy'), -12)
28 and trunc(p_date, 'yyyy')-1
29 then amount
30 else 0
31 end
32 ) as year,
33 sum( decode (date_, add_months(p_date, -12), amount, 0) ) as day,
34 sum( case
35 when date_ between
36 trunc(p_date, 'MM') and
37 last_day(p_date)
38 then amount
39 else
40 0
41 end
42 ) as month
43 from t_test
44 inner join t_default_date on (date_ between add_months(trunc(p_date, 'yyyy'), -12) and last_day(p_date) );
YEAR DAY MONTH
---------- ---------- ----------
1236 521 231
SQL>
This makes use of add_months to get exactly "one year ago"; if you need "365 days ago" (think of leap years), consider using something like date - 365

Get subobject of object in hierarchy

with sample_data as (select '26.03.2015 14:10' as adate, 4 as type, 40 as object, 111 as barcode from dual union all
select '26.03.2015 14:09' as adate, 1 as type, 55 as object, 222 as barcode from dual union all
select '26.03.2015 14:08' as adate, 2 as type, 33 as object, 777 as barcode from dual union all
select '26.03.2015 14:08' as adate, 2 as type, 34 as object, null as barcode from dual union all
select '26.03.2015 13:20' as adate, 3 as type, 41 as object, null as barcode from dual union all
select '26.03.2015 12:00' as adate, 1 as type, 56 as object, 444 as barcode from dual union all
select '26.03.2015 11:59' as adate, 2 as type, 37 as object, 555 as barcode from dual union all
select '26.03.2015 11:59' as adate, 2 as type, 48 as object, null as barcode from dual)
select
adate, type, object, barcode
from sample_data
where type in (1, 2);
type 1 is finished building, type 2 is part of assembly
i need next result
55 | 222 | 26.03.2015 14:08 | 33
55 | 222 | 26.03.2015 14:08 | 34
56 | 444 | 26.03.2015 11:59 | 37
56 | 444 | 26.03.2015 11:59 | 38
so we see what object 55 contain subobject 33, 34 and two date = 26.03.2015 14:08
and object 56 contain subobject 37, 38 and two date = 26.03.2015 11:59
in begin i know two parameters - date and barcode of finished building, for example on my data - date 26.03.2015 14:09 and barcode 222 or date 26.03.2015 12:00 and barcode 444
This query does the job. Subquery T1 connects "types 1" with "types 2". T2 enumerates them using function row_number().
Last query filters only rows with rn = 1.
with t1 as (
select t.*, prior object pob, prior barcode pbc,
prior adate pad, level, sys_connect_by_path(object, '-') pth
from sample_data t where level=2
connect by prior adate > adate and prior type = 1 and type = 2),
t2 as (select t1.*,
row_number() over (partition by object order by pad) rn from t1 )
select pob, pbc, adate, object from t2 where rn = 1
Result:
POB PBC ADATE OBJECT
---------- ---------- ------------------- ----------
55 222 2015-03-26 14:08:00 33
55 222 2015-03-26 14:08:00 34
56 444 2015-03-26 11:59:00 37
56 444 2015-03-26 11:59:00 48
you have to define groups and then you can assign the items to the groups
with sample_data as (select '26.03.2015 14:10' as adate, 4 as type, 40 as object, 111 as barcode from dual union all
select '26.03.2015 14:09' as adate, 1 as type, 55 as object, 222 as barcode from dual union all
select '26.03.2015 14:08' as adate, 2 as type, 33 as object, 777 as barcode from dual union all
select '26.03.2015 14:08' as adate, 2 as type, 34 as object, null as barcode from dual union all
select '26.03.2015 13:20' as adate, 3 as type, 41 as object, null as barcode from dual union all
select '26.03.2015 12:00' as adate, 1 as type, 56 as object, 444 as barcode from dual union all
select '26.03.2015 11:59' as adate, 2 as type, 37 as object, 555 as barcode from dual union all
select '26.03.2015 11:59' as adate, 2 as type, 48 as object, null as barcode from dual),
sd_groups as (select adate, lag(adate, 1) over (order by adate) adate_last, object, barcode from (
select * from sample_data where type = 1
union all select min(adate), null, null, null from sample_data))
select sg.object, sg.barcode, sd.adate, sd.object
from sample_data sd, sd_groups sg
where sd.type = 2 and sd.adate between sg.adate_last and sg.adate;

Resources