Table:
CompanyID Lead LeadManager
------------------------------
1 2 3
Required output:
CompanyID Role RoleID
--------------------------------
1 Lead 2
1 Leadmanager 3
You can use union all to unpivot your dataset. This is a standard solution that works across most (if not all) RDBMS:
select companyID, 'Lead' role, Lead from mytable
union all select companyID, 'LeadManager', LeadManager from mytable
You can use apply to unpivot the data:
select v.*
from t cross apply
(values (t.CompanyId, 'Lead', t.Lead),
(t.CompanyId, 'LeadManager', t.LeadManager)
) v(CompanyId, Role, RoleId);
The advantage to this approach is that it scans the original table only once. This can be particular helpful when the "table" is a complex query.
Related
I was asked this question during an interview for a Junior Oracle Developer position, the interviewer admitted it was a tough one:
Write a query/queries to check if the table 'employees_hist' is an exact copy of the table 'employees'. Any ideas how to go about this?
EDIT: Consider that tables can have duplicate records so a simple MINUS will not work in this case.
EXAMPLE
EMPLOYEES
NAME
--------
Jack Crack
Jack Crack
Jill Hill
These two would not be identical.
EMPLOYEES_HIST
NAME
--------
Jack Crack
Jill Hill
Jill Hill
If the tables have the same columns, you can use this; this will return no rows if the rows in both tables are identical:
(
select * from test_data_01
minus
select * from test_data_02
)
union
(
select * from test_data_02
minus
select * from test_data_01
);
Identical regarding what? Metadata or the actual table data too?
Anyway, use MINUS.
select * from table_1
MINUS
select * from table_2
So, if the two tables are really identical, i.e. the metadata and the actual data, it would return no rows. Else, it would prove that the data is different.
If, you receive an error, it would mean the metadata itself is different.
Update If the data is not same, and that one of the table has duplicates.
Just select the unique records from one of the table, and simply apply MINUS against the other table.
One possible solution, which caters for duplicates, is to create a subquery which does a UNION on the two tables, and includes the number of duplicates contained within each table by grouping on all the columns. The outer query can then group on all the columns, including the row count column. If the table match, there should be no rows returned:
create table employees (name varchar2(100));
create table employees_hist (name varchar2(100));
insert into employees values ('Jack Crack');
insert into employees values ('Jack Crack');
insert into employees values ('Jill Hill');
insert into employees_hist values ('Jack Crack');
insert into employees_hist values ('Jill Hill');
insert into employees_hist values ('Jill Hill');
with both_tables as
(select name, count(*) as row_count
from employees
group by name
union all
select name, count(*) as row_count
from employees_hist
group by name)
select name, row_count from both_tables
group by name, row_count having count(*) <> 2;
gives you:
Name Row_count
Jack Crack 1
Jack Crack 2
Jill Hill 1
Jill Hill 2
This tells you that both names appear once in one table and twice in the other, and therefore the tables don't match.
select name, count(*) n from EMPLOYEES group by name
minus
select name, count(*) n from EMPLOYEES_HIST group by name
union all (
select name, count(*) n from EMPLOYEES_HIST group by name
minus
select name, count(*) n from EMPLOYEES group by name)
You could merge the two tables and then subtract one of the tables from the result. If the result of the subtraction is an empty table then you know that the the tables must be the same since merge had no effect (every row and column were effectively the same)
How do I merge two tables with different column number while removing duplicates?
That link provides a good way to merge the two tables without duplicates without knowing what the columns are.
Ensure the rows are unique by adding a pseudo column
WITH t1 AS
(SELECT <All_Columns>
, row_number() OVER
(PARTITION BY <All_Columns>
ORDER BY <All_Columns>) row_num
FROM employees)
, t2 AS
(SELECT <All_Columns>
, row_number() OVER
(PARTITION BY <All_Columns>
ORDER BY <All_Columns>) row_num
FROM employees_hist)
(SELECT *
FROM t1
MINUS
SELECT *
FROM t2
UNION ALL
(SELECT *
FROM t1
MINUS
SELECT *
FROM t2)
Use row_number to make sure there are no duplicate rows. Now you can use minus and if there are no results, the tables are identical.
SELECT ROW_NUMBER() OVER (Order By Name), *
FROM tab1
MINUS
SELECT ROW_NUMBER() OVER (Order By Name), *
FROM tab2
I used the following query and it returned what I wanted it to return, but I'm having a tough time wrapping my head around what the query is doing.
Query is nothing fancier than what's in the title: select distinct(count(*)) from table1
Distinct is not required in your SQL ,as you are going to get only result, count(*) without group by clause returns, count of all rows within that table.
Hence try this :
select count(*) from table1
Distinct is used for finding distinct values from a group of values:
say you have table1 , with column1 as :
Column1
----------
a
a
b
b
a
c
following sqls are run you will get output as :
1) select count(*) from table1
output :6
2) select distinct(count(*)) from table1
output :6
3) select count( distinct column1) from table1
output :3
Usually distinct is used inside count preferably with a particular column .
select count( distinct column_name_n ) from table1
The distinct is redundant... Select Count(*) with only one table can only generate one value, so distinct (which would eliminate duplicates) is irelelvant.
If you had multiple outputs, (if for example you were grouping on something) then it would cause the query to only display one output row for every distinct value of count(*) that would other wise be generated...
if, for example, you had
name
Bob
Bob
Bob
Bob
Mary
Mary
Mary
Mary
Dave
Dave
Al
George
then
select count(*)
From table
group By name
would result in
4
4
2
1
1
but
select distinct count(*)
From table
group By name
would result in
4
2
1
Does anyone happen to know a way of basically taking the 'Distinct' command but only using it on a single column. For lack of example, something similar to this:
Select (Distinct ID), Name, Term from Table
So it would get rid of row with duplicate ID's but still use the other column information. I would use distinct on the full query but the rows are all different due to certain columns data set. And I would need to output only the top most term between the two duplicates:
ID Name Term
1 Suzy A
1 Suzy B
2 John A
2 John B
3 Pete A
4 Carl A
5 Sally B
Any suggestions would be helpful.
select t.Id, t.Name, t.Term
from (select distinct ID from Table order by id, term) t
You can use row number for this
Select ID, Name, Term from(
Select ID, Name, Term, ROW_NUMBER ( )
OVER ( PARTITION BY ID order by Name) as rn from Table
Where rn = 1)
as tbl
Order by determines the order from which the first row will be picked.
What is the best way categorize records based on logic?
For example, from this table:
ID House Farm
1 (null) (null)
I would like to output:
ID Missing
1 House
1 Farm
Aside from the obvious UNION all below, is there a better way? Maybe a case when? UNION ALL will not be easily flexible when dealing with a bigger number of conditions.
select ID, 'House' as Missing from table where house is null
union all
select ID, 'Farm' as Missing from table where farm is null
While I don't know if it's more efficient than UNION ALL, another option is to use UNPIVOT depending on the version of Oracle you are using:
SELECT ID, Missing
FROM (
SELECT *
FROM YourTable
UNPIVOT INCLUDE NULLS (IsMissing FOR Missing IN (House as 'House', Farm as 'Farm'))
) t
WHERE IsMissing IS NULL
And here is the SQL Fiddle.
Please check the result using UNPIVOT. Check the links pivot and unpivot queries in 11g, PIVOT and UNPIVOT Operators in Oracle Database 11g Release 1 for more details.
SELECT
ID, MISSING
FROM
(
SELECT ID, NVL(HOUSE, 1) HOUSE, NVL(FARM, 1) FARM FROM YourTable
)x
UNPIVOT (
DCol
FOR MISSING
IN (HOUSE, FARM)
);
or
SELECT
ID, MISSING
FROM YourTable
UNPIVOT INCLUDE NULLS (
DCol
FOR MISSING
IN (HOUSE, FARM)
);
If I have a table such as
1 bob
1 ray
1 bob
1 ray
2 joe
2 joe
And I want to select distinct based on the two columns so that I would get
1 bob
1 ray
2 joe
How can I word my query? Is the only way to concatenate the columns and wrap them around a distinct function operator?
select distinct id, name from [table]
or
select id, name from [table] group by id, name
You can just do:
select distinct col1, col2 from your_table;
That's exactly what the distinct operator is for: removing duplicate result rows.
Keep in mind that distinct is usually a pretty expensive operation, since, after processing the query, the DB server might perform a sort operation in order to remove the duplicates.