Join tables with non distinct values in Oracle - oracle

I have this query which returns active users for our EBS system. Im trying to join this results with one more table in order to get theirs supervisor id but my problem is that i get cartesian product when trying to join with email address column of table EMPDATA_IMPORT. I need to use email column, because i do not have employee id populated for some users in fnd_user table.
SELECT
fu.user_name "User name", frt.responsibility_name "Responsibility Name" ,
furg.start_date "Start Date" , furg.end_date "End Date" ,
fu.last_logon_date "Last Logon Date", fr.responsibility_key "Responsibility key",
fu.email_address "Email Address", fu.description "Description", x.supervisor_id
FROM
fnd_user_resp_groups_direct furg, fnd_user fu,
applsys.fnd_responsibility_tl frt, applsys.fnd_responsibility fr, EMPDATA_IMPORT x
WHERE furg.user_id = fu.user_id
AND furg.responsibility_id = frt.responsibility_id
AND fr.responsibility_id = frt.responsibility_id
AND (to_char(fu.END_DATE) is null OR fu.END_DATE > sysdate)
and fu.email_address=x.EMAIL_ADDRESS -- x has non distinct values for email address
Ok i will try to describe table data for EMPDATA_IMPORT :
Emp_id Full_name supervisor_id email_address
10 John Doe 100 jdoe#mm.com
10 John Doe 100 jdoe#mm.com
10 John Doe 100 jdoe#mm.com
100 Mike King 200 mking#mm.com
One other thing, by joining with email column above one i need to somehow present manager's name (using supervisor id) in above query. I cant figure it out....
How to manage this?
Thanks

Related

Oracle SQL - How to add a filter on a case field that I created?

I'm relatively new to Oracle SQL and have run into an issue where I'm trying to filter a report to only return records logged by a specific list of user names.
They are currently stored in the system in fields user.first_name and user.surname and I've created the following CAST field in the coding to join the two together:
CAST(USER.FIRST_NAME||' '||USER.SURNAME as VARCHAR (25)) as CUSTOMER
What I want to do now though is restrict it so that my query will only return records where the customer is in a pre-determined list that I can hard core into the SQL.
eg I only want to see records for :
Joe Bloggs,
John Doe,
A Nother
How do I do this in Oracle SQL?
Thanks
One option (as you said you hardcoded it) is
select *
from your_table
where customer in ('Joe Bloggs', 'John Doe', 'A Nother');
A better one is to store those customers into a separate table and join it with your_table:
insert into separate_table (name) values ('Joe Bloggs'); -- do the same for the rest
select *
from your_table y join separate_table s on s.name = y.first_name ||' '||i.surname;
Even better, use their IDs (because, there could be two John Doe persons; which one will you take)?
insert into separate_table (id) values (1123); -- this is Joe Bloggs
select *
from your_table y join separate_table s on s.id = y.id;

How to avoid duplicate field name in query result

I am developing a padrino web application. I have two tables:
User table: Has id, name, address fields
Post table: Has id, user_id, content
If I join them,
User.join(:posts, user_id:, :id)
they return two fields with the same name id:
id name address id user_id content
1 jim *** 3 1 post1
I would like to rename each of these ids. I want the result to be:
u_id name address p_id user_id content
1 jim *** 3 1 post1
I am using Sequel adapter for postgresql db in padrino project.
In mysql query, it will be like this:
select u.id as u_id,
u.name,
u.address,
p.id as p_id,
p.user_id as user_id,
p.content
from users u
join posts p on u.id = p.user_id
what should I do?
What I want is not sql query, but code of ruby language. Thanks.
You should use Dataset#select to set which columns are being selected:
User.from{users.as(:u)}.join(Sequel[:posts].as(:p), user_id: :id).
select{[u[:id].as(:u_id), u[:name], u[:address],
p[:id].as(:p_id), p[:user_id].as(:user_id), p[:content]]}

Custom Reporting Table Query Boolean Column

I am new to Kentico and really enjoy developing so far! I have exhausted all search efforts and thought I'd reach out to the community. I am creating a custom report (table to be exact) using the reporting built into Kentico. I have a custom query:
Select FirstName as [First Name], LastName as [Last Name], Email, Phone, StreetAddress as [Street Address], City, State, Country, Zip, Email, Phone, PaymentDate as [Payment Date], TransactionID as [Transaction ID], PaymentStatus as [Payment Status]
from TableName E
WHERE E.ID = 1 AND E.PaymentStatus = False
ORDER BY E.ItemCreatedWhen ASC
The issue that I find is that PaymentStatus is coming thru as a "Checkbox - unchecked or checked" instead of True or False. In the actual table and data it shows True/False. Is there any way around this? Thanks for your help!
I get the same checkbox, you can get a text value instead by wrapping your boolean (bit) field in a CASE. Your Report table Query would look like this;
SELECT FirstName as [First Name], LastName as [Last Name], Email, Phone, StreetAddress as [Street Address], City, State, Country, Zip, Email, Phone, PaymentDate as [Payment Date], TransactionID as [Transaction ID],
CASE WHEN PaymentStatus = 0 THEN 'False'
ELSE 'True'
END as [Payment Status]
FROM TableName E
WHERE E.ID = 1
AND E.PaymentStatus = False
ORDER BY E.ItemCreatedWhen ASC

Hive query to find the ip address and country which is not present

I have a Hive table named 'Login'. It contains the following columns :-
UserID | UserName | UserIP | UserCountry | Date
On a particular day (all that logins of that day), I want to find out the UserIDs, which has been accessed from a country (UserCountry) from where the user has never accessed his account from OR the IPs (UserIP) from which the account has never been accessed before.
I would start with an except where I remove prior countries and IPs
select userid, usercountry, userip
from table
where date=xx
except
select userid, usercountry, userip
from table
where date<xx
I think that the best way is the GROUP clause!
You say "has never been accessed before", means COUNT = 1.
To find the IP use only once :
select UserId, UserIP, COUNT(UserIP) FROM Login WHERE Date = yourdate GROUP BY UserIP, UserId HAVING COUNT(UserIP) = 1
To find the country use only once :
select UserId, UserCountry, COUNT(UserCountry) FROM Login WHERE Date = yourdate GROUP BY UserCountry, UserId HAVING COUNT(UserCountry) = 1
Left Outer Join will be able to satisfy your requirement in HIVE.
select t1.userid, t1.usercountry, t1.userip
from table t1
LEFT OUTER JOIN
from table t2
ON (t1.userid=t2.userid)
WHERE t1.date=xx and
t2.data < xx and
(t2.usercountry IS NULL or
t2.userip IS NULL);
Hope this helps...

SQL Query Performance with count

I have 2 tables, COMPANY and EMPLOYEE.
COMPANY_ID is the primary key of the COMPANY table and foreign key for EMPLOYEE table. The COMPANY_ID is a 10 digit number. We are generate a 3 number combination and query the database.
The select statement has regex to bulk load the company based on COMPANY_ID. The query is executed multiple times with different patterns
i.e.
regexp_like(COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)') .
Existing query looks something like this -
select *
from COMPANY company
where regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
The new requirement is to retrieve the company information along with the employee count. For example if a company has 10 employees, then the query should return all the columns of the COMPANY table, along with employee count i.e. 10
This is the select statement that I came up with -
select
nvl(count_table.cont_count, 0), company.*
from
COMPANY company,
(select company.COMPANY_ID, count(company.COMPANY_ID) as cont_count
from COMPANY company, EMPLOYEE employee
where regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
and company.CONTACT_ID = employee.CONTACT_ID
group by (company.COMPANY_ID)) count_table
where
regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
and count_table.COMPANY_ID(+)= company.COMPANY_ID
Above query works, but it takes double the time compared to the previous statement. Is there a better way to retrieve the employee count?
Note: Oracle database is in use.
You don't need to execute that expensive REGEXP_LIKE twice:
select nvl(count_table.cont_count,0),company.*
from COMPANY company
,( select employee.COMPANY_ID, count(employee.COMPANY_ID) as cont_count
from EMPLOYEE employee
group by (employee.COMPANY_ID)
) count_table
where regexp_like(company.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
and count_table.COMPANY_ID(+)= company.COMPANY_ID
Or you could use a scalar subquery:
select company.*
, (select count(*)
from employee e
where e.company_id = c.company_id
)
from COMPANY c
where regexp_like(c.COMPANY_ID, '^(000|001|002|003|004|005|006|007|008|009)')
And personally I would ditch the slow REGEXP_LIKE for something like:
where substr(c.company_id,1,3) between '000' and '009'
The derived table does not add value, thus I would get rid of it and use a scalar query (because I do not know all of your columns in the company table to properly do a group by):
select c.*,
nvl(
(select count(1)
from employee emp
where emp.company_id = c.company_id
),0) employee_count
from company c
where regexp_like(c.company_id, '^(000|001|002|003|004|005|006|007|008|009)')
Also, if performance is still an issue, I would consider modifying your where statement to not use a regexp.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Addendum
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
I see that the question explicitly identifies that the employee table has company_id as a foreign key. Since this is clarified, I am removing this statement:
The data model for these tables is not intuitive (would you not have
company_id as a foreign key in the employees table?).

Resources