Oracle : select maximum value from different columns of the same row - sql

The whole question is pretty much in the title. For each row of the table I'd like to select the maximum of a subset of columns.
For example, from this table
name m1 m2 m3 m4
A 1 2 3 4
B 6 3 4 5
C 1 5 2 1
the result would be
name max
A 4
B 6
C 5
The query must be compatible oracle 8i.

Given this test data ...
SQL> select *
2 from your_table
3 /
NAME M1 M2 M3 M4
---- ---------- ---------- ---------- ----------
A 1 2 3 4
B 6 3 4 5
C 1 5 2 1
SQL>
... a straightforward GREATEST() call will give the desired result:
SQL> select name
2 , greatest(m1, m2, m3, m4) as the greatest_m
3 from your_table
4 /
NAME THE_GREATEST_M
---- --------------
A 4
B 6
C 5
SQL>
Note that greatest() will return NULL if any of the arguments are null. If this is a problem then use nvl() to provide a default value which won't distort the outcome. For instance, if no values can be negative....
SQL> select name
2 , greatest(nvl(m1,0), nvl(m2,0), nvl(m3,0), nvl(m4,0)) as the greatest_m
3 from your_table
4 /
NAME THE_GREATEST_M
---- --------------
A 4
B 6
C 5
SQL>

Use GREATEST but also handle possible NULL's
SELECT name, GREATEST(NVL(m1,0), NVL(m2,0), NVL(m3,0), NVL(m4,0)) AS "Max"
FROM yourtable
Input:
name m1 m2 m3 m4
A 1 2 3 4
B 6 3 4 5
C 1 5 2 1
Output:
NAME Max
A 4
B 6
C 5
SQL Fiddle: http://sqlfiddle.com/#!4/ae268/7/0
Input:
name m1 m2 m3 m4
A 1 2 3 null
B 6 null 4 5
C 1 5 2 1
Output:
NAME Max
A 3
B 6
C 5
SQL Fiddle: http://sqlfiddle.com/#!4/b1c46/1/0

Related

Add entries of a table into rows of another table

I have two tables
table a:
ID VALUE_z
1 41
2 32
3 51
table b:
ID TYPE z
1 a 10
1 b 15
1 c 20
2 a 12
2 b 8
2 c 5
3 a 21
3 b 4
3 c 2
I want to add the rows from table a to the column VALUE in table b based on the ID. The result should look like this
table result:
ID TYPE VALUE
1 a 10
1 b 15
1 c 20
1 z 41
2 a 12
2 b 8
2 c 5
2 z 32
3 a 21
3 b 4
3 c 2
3 z 51
Try the following using INSERT INTO SELECT Statement:
insert into tableB
select ID, 'z', VALUE_z
from tableA
See demo

Merge same SQL database values in table and relating table

sure it could solved one by one, for each value in specified column but I was looking for an more elegant way, handled by one SQL query.
Following mini database:
Two material tables:
Table MatA:
ID NomCom_ID ProFo_ID
1 1 1
2 2 2
Table MatB:
ID NomCom_ID ProFo_ID
1 1 2
2 2 2
One note table:
Table Note:
ID Val MatTab
1 S6 A
2 T1 A
3 W10 A
4 W12 A
5 S5 B
6 T1 B
7 G10 B
8 T1 XXX
9 W10 XXX
10 G8 XXX
And one table for relation between notes and Materials:
Table RelateNoteMat:
ID Mat_ID Note_ID
1 1 1
2 1 2
3 2 2
4 2 3
5 1 8
6 1 10
at a later time it's clear, that MatTab 'XXX' is MatTab 'A'
so I want to update Table Note and Table RelateNoteMat like this:
Table Note:
ID Val MatTab
1 S6 A
2 T1 A
3 W10 A
4 W12 A
5 S5 B
6 T1 B
7 G10 B
8 G8 A
And one table for relation between notes and Materials:
Table RelateNoteMat:
ID Mat_ID Note_ID
1 1 1
2 1 2
3 2 2
4 2 3
5 1 8
is this possible with one SQL query?

Fill in sequence numbers in sql oracle

I have a table that includes two columns, these columns have ranges i.e
Batch from _serial_no to_serial_no
a 1 5
b 2 7
I want to create another column to fill in the gaps for a abd b separately
Something like this
Batch from _serial_no to_serial_no seq_number
a 1 5 1
a 1 5 2
a 1 5 3
a 1 5 4
a 1 5 5
b 2 7 2
b 2 7 3
b 2 7 4
b 2 7 5
b 2 7 6
b 2 7 7
Is there an sql I could use?
I tried something like this but it didn't work
select *
from (
select a.*,rownum n
from my_table a connect by level <= TO_SERIAL_NO
)
where n >= FROM_SERIAL_NO;
SQL> with
2 data as (select 'a' batch, 1 from_serial_number, 5 to_serial_number from dual
3 union all
4 select 'b' batch, 2 from_serial_number, 7 to_serial_number from dual),
5 seq as (select rownum n# from dual connect by level <= (select max(to_serial_number) from data))
6 select
7 data.*,
8 seq.n#
9 from
10 data,
11 seq
12 where
13 seq.n# between data.from_serial_number and data.to_serial_number
14 order by
15 1, 2, 4;
BATCH FROM_SERIAL_NUMBER TO_SERIAL_NUMBER N#
----- ------------------ ---------------- ----------
a 1 5 1
a 1 5 2
a 1 5 3
a 1 5 4
a 1 5 5
b 2 7 2
b 2 7 3
b 2 7 4
b 2 7 5
b 2 7 6
b 2 7 7
11 rows selected
Yet another option:
SQL> with test (batch, from_serial_no, to_serial_no) as
2 (select 'a', 1, 5 from dual union
3 select 'b', 2, 7 from dual
4 )
5 select
6 batch,
7 from_serial_no,
8 to_serial_no,
9 froM_serial_no + column_value - 1 seq_number
10 from test,
11 table(cast(multiset(select level from dual
12 connect by level <= to_serial_no - from_serial_no + 1
13 ) as sys.odcinumberlist))
14 order by batch, seq_number;
B FROM_SERIAL_NO TO_SERIAL_NO SEQ_NUMBER
- -------------- ------------ ----------
a 1 5 1
a 1 5 2
a 1 5 3
a 1 5 4
a 1 5 5
b 2 7 2
b 2 7 3
b 2 7 4
b 2 7 5
b 2 7 6
b 2 7 7
11 rows selected.
SQL>
Using a join
select d.*, t.seq_number
from data d
join
(
SELECT from_serial_no + level - 1 seq_number
FROM (select min(from_serial_no) from_serial_no,
max(to_serial_no) to_serial_no
from data) t
CONNECT BY from_serial_no + level - 1 <= to_serial_no
) t on d.from_serial_no <= t.seq_number and
d.to_serial_no >= t.seq_number
order by d.batch, t.seq_number;
dbfiddle demo

See if all records in the same group are of accepted types

Consider the following table. Each document (id) belongs to a group (group_id).
-----------------------
id group_id value
-----------------------
1 1 A
2 1 B
3 1 D
4 2 A
5 2 B
6 3 C
7 4 A
8 4 B
9 4 B
10 4 B
11 4 C
12 5 A
13 5 A
14 5 A
15 6 B
16 6 NULL
17 6 NULL
18 6 D
19 7 NULL
20 8 B
1/ Each document has a value NULL, A, B, C or D
2/ If the documents in the same group all have either A or B as value, the group is completed
3/ In this case, the desired output would read:
---------------------
group_id completed
---------------------
1 0 <== because document 3 = D
2 1 <== all documents have either A or B as a value
3 0 <== only one document in the group, value C
4 1 <== all documents have either A or B as a value
5 1 <== all documents have value A
6 0 <== because of NULL values and value D
7 0 <== NULL
8 1 <== only one document, value B
IS it possible to query this resultset?
As I am not very experienced in SQL, any help would be appreciated!
Try this
SELECT [group_id],
CASE
WHEN Count(CASE WHEN [value] IN ( 'A', 'B' ) THEN 1 END) = Count(*) THEN 1
ELSE 0
END AS COMPLETED
FROM yourtable
GROUP BY [group_id]

Trouble with groupss and aggregation

I'm trying to use pandas to select a single result from a group of results, where some column has a minimum value. An example table representing my data frame is:
ID q A B C D
---------------
1 10 1 2 3 4
1 5 5 6 7 8
2 1 9 1 2 3
2 2 8 7 6 5
I would like to group by ID and then select the row that has the smallest q for each group. So, the second row corresponding to ID=1 and the first row corresponding to ID=2 to be selected.
I can only select the lowest values of each column, which is not what I need. Thanks a lot to anybody who can offer some guidance.
This should do what you're asking:
In [10]: df.groupby('ID').apply(lambda x: x.ix[x['q'].idxmin()])
Out[10]:
ID q A B C D
ID
1 1 5 5 6 7 8
2 2 1 9 1 2 3
Apply a function that returns the group row that has the index of the minimum 'q' value.