Oracle - update , decode and set value - sql

I have a table e.g.
**Fruit Number**
Apple 5
Grape 9
Orange 1
Coconut 54
Mango 22
I want to :
Select the whole list
Put 'Apple, Mango,Coconut' at top of the list.
Update the current order, where number = rownum
The list should look as follows :
**Fruit Number**
Apple 1
Mango 2
Coconut 3
Grape 4
Orange 5
I tried the following however getting syntax issues ..
update tablename
set id = rownum
where fruit in (select fruit from table order by decode(fruit,'Apple',1,'Mango',2,'Coconut',3))

UPDATE (
SELECT ROWNUM+5 AS r, fruit, number FROM TABLE
WHERE fruit NOT IN ('Apple', 'Mango', 'Coconut', 'Grape', 'Orange')
UNION
SELECT 1 AS r, 'Apple' AS fruit, number FROM TABLE
UNION
SELECT 2 AS r, 'Mango' AS fruit, number FROM TABLE
UNION
SELECT 3 AS r, 'Coconut' AS fruit, number FROM TABLE
UNION
SELECT 4 AS r, 'Grape' AS fruit, number FROM TABLE
UNION
SELECT 5 AS r, 'Orange' AS fruit, number FROM TABLE
)
SET number = r;

Following query will do that for you.
UPDATE table SET number =
CASE fruit
WHEN 'Apple' THEN 1
WHEN 'Mango' THEN 2
WHEN 'Coconut' THEN 3
WHEN 'Grape' THEN 4
WHEN 'Orange' THEN 5
END;

Related

Selecting MAX of a Value from multiple categories from a table

I am looking to get the max weight of Apple, Orange, Mango - there could be any number of fruits. Bold items from the table is what i would like to have my query response.
I know this can be done by partitioning the table for example:
SELECT fruits,max(weight) OVER(PARTITION BY fruits)
FROM fruitstat
GROUP BY fruits;
But this is not getting my expected results. I need the ones which are the max weight fruits in its category.
Fruits
Color
Weight
Apple
red
23
Orange
orange
6
Mango
yellow
13
Apple
red
15
Orange
orange
19
Mango
yellow
16
Apple
red
44
Orange
orange
31
Mango
yellow
12
Apple
red
14
Orange
orange
22
Mango
yellow
11
Just group the MAX(weight) by fruits:
WITH fruit AS
(
SELECT 'Apple' as fruits,'red' as color ,23 as weight FROM dual UNION ALL
SELECT 'Orange','orange',6 FROM dual UNION ALL
SELECT 'Mango','yellow',13 FROM dual UNION ALL
SELECT 'Apple','red',15 FROM dual UNION ALL
SELECT 'Orange','orange',19 FROM dual UNION ALL
SELECT 'Mango','yellow',16 FROM dual UNION ALL
SELECT 'Apple','red',44 FROM dual UNION ALL
SELECT 'Orange','orange',31 FROM dual UNION ALL
SELECT 'Mango','yellow',12 FROM dual UNION ALL
SELECT 'Apple','red',14 FROM dual UNION ALL
SELECT 'Orange','orange',22 FROM dual UNION ALL
SELECT 'Mango','yellow',11 FROM dual
)
SELECT fruits, MAX(weight)
FROM fruit
GROUP BY fruits;
P.S. MAX for the apple is 44, not 23, at least in your sample data
You don't need to use group by on window functions. You can do this, instead.
First, sort the fruits weight by using rank.
select rank() over (partition by fruits order by weight) as rank, fruits, weight
from fruitstat
After that, you can use subquery to return the first value only.
select fruits, weight
from (select rank() over (partition by fruits order by weight) as rank, fruits, weight from fruitstat) a
where rank = 1

ORACLE SQL: Reseting a counting sequence when ID ends for the next one

I am currently trying to reset a sequence if an ID of a Customer ends
right now, it is something like this:
CustomerID Product PosNr
1 Banana 1
1 Papaya 2
1 Apple 3
2 Laptop 1
2 Keyboard 2
I hope it is clear what I mean.
The PosNr should reset for another Customer.
Can I Set up something like this while inserting the values into the table, or in any other way?
It is row_number analytic function with appropriate partitioning.
SQL> with test (customerid, product) as
2 (select 1, 'banana' from dual union all
3 select 1, 'papaya' from dual union all
4 select 1, 'apple' from dual union all
5 select 2, 'laptop' from dual union all
6 select 2, 'keyboard' from dual
7 )
8 select customerid, product,
9 row_number() over (partition by customerid order by product) posnr
10 from test
11 /
CUSTOMERID PRODUCT POSNR
---------- -------- ----------
1 apple 1
1 banana 2
1 papaya 3
2 keyboard 1
2 laptop 2
SQL>

Count the number of times word appears in a single column

I'm attempting to count the number of times apples and oranges appear in my fruit column.
The table looks like this:
Fruit
-------
Apples
Apples Oranges
Apples Oranges
Apples
Oranges
Expected output:
Apples 4
Oranges 3
My code thus far. I'm not sure how to do it when both appear and how to add them to the totals. I'm sure there is an easier way that this.
SELECT
COUNT (CASE WHEN Fruit LIKE '%Apples%' THEN '1' END) AS Apples
COUNT (CASE WHEN Fruit LIKE '%Oranges%' THEN '1' END) AS Oranges
FROM Fruits
Cheers
If those fruits are single-worded and separated by a space, then such a generic approach might be interesting for you.
Lines #1 - 8 represent sample data; you already have that so you don't type it. Code you might need starts at line #10.
SQL> with fruit (fruit) as
2 -- sample data; you have that in a table
3 (select 'Apples' from dual union all
4 select 'Apples Oranges' from dual union all
5 select 'Apples Oranges' from dual union all
6 select 'Apples Lemon' from dual union all
7 select 'Oranges Plums' from dual
8 ),
9 -- split fruits to rows
10 temp as
11 (select regexp_substr(fruit, '[^ ]+', 1, column_value) fruit
12 from fruit cross join
13 table(cast(multiset(select level from dual
14 connect by level <= regexp_count(fruit, ' ') + 1
15 ) as sys.odcinumberlist))
16 )
17 select fruit, count(*)
18 from temp
19 group by fruit
20 order by fruit;
FRUIT COUNT(*)
-------------------------------------------------------- ----------
Apples 4
Lemon 1
Oranges 3
Plums 1
SQL>
Either with sum or count, it works
Connected to:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production
SQL> with t as
(
select 'Apples' as fruits from dual union all
select 'Apples Oranges' as fruits from dual union all
select 'Apples Oranges' as fruits from dual union all
select 'Apples' as fruits from dual union all
select 'Oranges' as fruits 6 from dual
) select
SUM (CASE WHEN fruits LIKE '%Apples%' THEN '1' END) AS Apples ,
SUM (CASE WHEN fruits LIKE '%Oranges%' THEN '1' END) AS Oranges
FROM t
;
APPLES ORANGES
---------- ----------
4 3
SQL> with t as
(
select 'Apples' as fruits from dual union all
select 'Apples Oranges' as fruits from dual union all
select 'Apples Oranges' as fruits from dual union all
select 'Apples' as fruits from dual union all
select 'Oranges' as fruits from dual
) select
COUNT (CASE WHEN fruits LIKE '%Apples%' THEN '1' END) AS Apples ,
COUNT (CASE WHEN fruits LIKE '%Oranges%' THEN '1' END) AS Oranges
FROM t ;
APPLES ORANGES
---------- ----------
4 3
SQL>

How to return distinct rows meeting condition

I have an example table in the format below with sample data:
=cust_table
Customer: Liked_Color:
Adam Blue
Adam Green
Adam Yellow
Adam Red
Bob Yellow
Bob Yellow
Bob Yellow
Bob Yellow
Charlie Red
Charlie Red
Charlie Red
Charlie Red
How can I select distinct customers and only return them if they DO NOT like the color Blue?
So, the returned results would be:
Customer: Bob, Charlie
If I do:
SELECT DISTINCT Customer
FROM cust_table
WHERE Liked_Color NOT LIKE Blue
I get: Adam, Bob, Charlie
How would I make sure the Customer is only returned when Blue is not a Liked_Color for a Customer?
I would use aggregation:
select customer
from cust_table
group by customer
having sum(case when color = 'Blue' then 1 else 0 end) = 0;
However, a customer table should have one row per customer (at least per unit time). If you had such a table and a customer_colors table, then I would use not exists:
select c.*
from customers c
where not exists (select 1
from customer_colors cc
where cc.customer = c.customer and cc.color = 'Blue'
);
This would also return customers with no preferred color at all, which you cannot do with your single table.
Alternatively, see whether sets do any good:
SQL> with cust (customer, liked_color) as
2 (select 'Adam' , 'Blue' from dual union all
3 select 'Adam' , 'Green' from dual union all
4 select 'Bob' , 'Yellow' from dual union all
5 select 'Bob' , 'Red' from dual union all
6 select 'Charlie', 'Red' from dual union all
7 select 'Charlie', 'Red' from dual
8 )
9 select customer from cust where liked_color <> 'Blue'
10 minus
11 select customer from cust where liked_color = 'Blue';
CUSTOME
-------
Bob
Charlie
SQL>
this will work the simplest of them all :
select distinct a from Table1 where a not in
(select distinct a from Table1 where b like 'Blue');
check fiddle:http://sqlfiddle.com/#!9/7034f/10

Transpose vertical input data to horizontal output in Oracle

I need to transpose rows to columns in Oracle. I've the data in this format:
Apple Orange Mango Banana
15 20 12 67
The required result is:
Fruit Number
Apple 15
Orange 20
Mango 12
Banana 67
I used Union to get this result but this is not the generic one.
SELECT ‘Apple’ AS Fruit, Apple AS Number FROM fruits_tbl UNION
SELECT ‘Orange’, Orange FROM fruits_tbl UNION
SELECT ‘Mango’, Mango FROM fruits_tbl UNION
SELECT ‘Banana’, Banana FROM fruits_tbl;
I want standard procedure to get the output as suggested.
Update: Figured out Pivot is the correct approach!
Since Oracle 11g (tab is your table name):
select * from tab
UNPIVOT (num for fruit in (apple as 'apple', orange as 'orange', mango as 'mango', banana as 'banana'));
Oracle 10g:
with col_names as (
select 'apple' fruit from dual
union all select 'orange' from dual
union all select 'mango' from dual
union all select 'banana' from dual
)
select c.fruit,
case c.fruit
when 'apple' then t.apple
when 'orange' then t.orange
when 'mango' then t.mango
when 'banana' then t.banana
end as num
from tab t
cross join col_names c;