Oracle query to select distinct Value based on another column value - sql

Consider the below sample table:
ID Value
123 ABC
456 DEF
456 ABC
I want the select query result as below:
ID Value
123 ABC
456 DEF
Note: ID has only 2 different values - "123" and "456". Selection should be based on Column "ID". If value "123" is present, the corresponding data from "Value" column has to be selected. If not "456" ID should be retrieved.

simple group by will help you to get the desired result
select min(id), value
from table
group by value

Some thing like this:
select min(id) as id,
Value
from table
group by Value, id

You can use the below if ID is a string like 456 is 'xxx' and 123 is 'yyy' The SQL fiddle here
WITH tt1
AS (SELECT Decode(id, '123', 1,
2) order1,
id,
value1
FROM tt),
tt2
AS (SELECT Min(order1) order1,
value1
FROM tt1
GROUP BY value1)
SELECT tt1.id,
tt1.value1
FROM tt2,
tt1
WHERE tt1.value1 = tt2.value1
AND tt1.order1 = tt2.order1;

Related

How to display one record into multiple records based on ID column

Probably very basic question but I have records like this
Value1- Value2- Value3- Value4- Value5- ID1
Value1- Value2- Value3- Value4- Value5- ID2
(Values 1 - 5 can be null)
I want to display it based on ID in this format:
ID1 - Value1
ID1 - Value2
ID2 - Value1
etc for all values that are not null.
Thanks!
it would be :
select ID,col
from Table
Unpivot
(
col for details in (column1,column2,column3,column4,column5)
) as UnPvt
Provided that you havent mentioned the database heres a general query if column "value" for each id has minimum no of values for each id
SELECT ID,
CASE WHEN VALUE =VALUE1
THEN VALUE END CASE,
..........
CASE WHEN VALUE =VALUEN
THEN VALUE END CASE
FROM TABLE GROUP BY ID;
You didn't specify the DBMS, but if you are using DB2, try to use LATERAL.
Select
A.ID, A_Column_Value
From
YOUR_TABLE A ,
LATERAL
(VALUES
A.COLUMN1,
A.COLUMN2,
A.COLUMN3) As All_Values (A_Column_Value)
You can try cross join with same entity and add conditions to avoid data redundancy.

Sql Query regarding Join

I have two tables as follows:
Table 1:
Name | Specialisation
Table2:
Name | Slot | Date
I take user input of Name, Slot and Date. I want to display the records of Table1 for that Name such that there exists no record corresponding to the entered (Name, Slot, Date) in Table 2. What will be the SQL query for it?
Thanks in advance.
Supposing the input values were input_name, input_slot, and input_data, and the input_date was a suitable date format, one way to do it would be:
select name, specialisation from table1
where (name = input_name)
and (select name from table2
where (table2.name = input_name) and
(table2.slot = input_slot) and
(table2.date = input_date)) is NULL
Or something like that... :)
You can use a not in
select name
from table1
where name not in (
select name from table2
)
or not exists
select name
from table1
where name not exists (
select name from table2
where table2.name = table1.name
)

Oracle SQL: Transpose / rotate a table result having one row and many columns

I'm looking for a way to transpose or rotate a table in Oracle SQL. For this case there is only one row in the SELECT, but multiple columns.
Example:
SELECT
id AS "Id",
name AS "Name",
some_value AS "Favorite color"
FROM
table
WHERE
id = 5;
Result:
id | name | some_value
--- ------ -----------
5 John Orange
What I would like to see is:
Id | 5
Name | John
Favorite color | Orange
I'm aware of PIVOT, but I'm struggling to see a simple code with this case.
You can unpivot the columns to get this result as follows:
select fld, val
from (
select to_char(id) as "Id", -- convert all columns to same type
name as "Name",
some_value as "Favorite color"
from your_table
where id = 5
) unpivot(val for fld in("Id", "Name", "Favorite color"));
Use simple UNION ALL clause
SELECT 'Id' As field_name, cast( id as varchar2(100)) as Value FROM "TABLE" where id = 5
UNION ALL
SELECT 'Name' , name FROM "TABLE" where id = 5
UNION ALL
SELECT 'Favorite color' , some_value FROM "TABLE" where id = 5;
Frank Ockenfuss gave the answer I was looking for. Thanks, Frank!
However, a minor change makes changing the column names a bit more easier:
SELECT * FROM (
SELECT
TO_CHAR(id) AS id,
TO_CHAR(name) AS name,
TO_CHAR(some_value) AS fav_color
FROM my_table
WHERE id = 5
) UNPIVOT(value FOR key IN(
id AS 'Id',
name AS 'Name',
fav_color AS 'Favorite color'
));
Result:
key | value
-------------- ------
Id 5
Name John
Favorite color Orange

Oracle SQL - return record only if colB is the same for all of colA

I have a table like the following ( there is of course other data in the table):
Col A Col B
1 Red
1 Red
2 Blue
2 Green
3 Black
I am trying to return a value for Col A only when ALL the Col B values match, otherwise return null.
This will be used as part of another sql statement that will be passing the Col A value, ie
Select * from Table where Col A = 1
I need to return the value in Col B. The correct result in the above table would be Red,Black
any ideas ?
how about this?
SQL Fiddle
Oracle 11g R2 Schema Setup:
create table t( id number, color varchar2(20));
insert into t values(1,'RED');
insert into t values(1,'RED');
insert into t values(2,'BLUE');
insert into t values(2,'GREEN');
insert into t values(3,'BLACK');
Query 1:
select color from t where id in (
select id
from t
group by id having min(color) = max(color) )
group by color
Results:
| COLOR |
|-------|
| RED |
| BLACK |
If you just want the values in A (rather than each row), then use group by:
select a
from table t
group by a
having min(b) = max(b);
Note: this ignores NULL values. If you want to treat them as an additional value, then add another condition:
select a
from table t
group by a
having min(b) = max(b) and count(*) = count(b);
It is also tempting to use count(distinct). In general, though, count(distinct) requires more processing effort than a min() and a max().
You can use a case statement.
select cola,
case when max(colb) = min(colb) and count(*) = count(colb) then max(colb)
end as colb
from tablename
group by cola
SQL Fiddle
Oracle 11g R2 Schema Setup:
create table t( id number, color varchar2(20));
insert into t values(1,'RED');
insert into t values(1,'RED');
insert into t values(2,'BLUE');
insert into t values(2,'GREEN');
insert into t values(3,'BLACK');
Query 1:
select id
from t
group by id having min(color) = max(color)
Results:
| ID |
|----|
| 1 |
| 3 |
hope this is what you were looking for.. :)

ISNULL or any alternative in sql server when not data present for subquery

I have a situation, Where I need to get some data in case I find no data for certain query. e.g.
select id from abc where userid='XYZ'
In this case I will get the Id, only if the record with userid='XYZ' is present in the table abc.
Below given code will give 123 only if id is present as null .This is not what I'm expecting.
select isnull(id,123) from abc where userid='XYZ'
I want something like:If no data in abc with userid='XYZ', then some specific value should be output. e.g.
select isnull((select id from abc where userid='XYZ'),123)
Is there any similar shortcut for the above query?? Please suggest. Thanks in advance
isnull work on the "column" level, what you need is if a row is null, then print something else.
I would UNION ALL your select with a "dummy" select containing only one row with the data you want to be displayed in case nothing returns, then select top 1 from that with a order. Like
select top 1 id
from (
select id, 1 from abc where userid='XYZ'
UNION ALL
select 123, 0
) X
order by 1 DESC
select top 1 id
from
(
select 1 as id, value from abc where userid='xyz'
union
select 2, 123
) v
order by ranking
You could use a variable if the result is only going to return one row.
DECLARE #Id INT;
SELECT #Id = id FROM abc WHERE userid='XYZ';
SET #Id = ISNULL(#Id, 123);
SELECT #Id AS Id;