subquerying in hive with left outer join or where exists - hive

I'm trying to do multiple nested subqueries. First find lowercase names with role "Person", then find session_ids that those people have had. With that list of session ids, I want to filter the original query, by all results that are in those session ids
select
U.session_id,
U.session_date,
U.email
from data.usage U
left outer join
select
distinct M.session_id
from data.usage M
where email like '%gmail.com%'
and data_date >= '20180101'
and name in
(
select
lower(name)
from data.users
where role like 'Person%'
and isactive = TRUE
and data_date = '20180412'
)
on U.session_id = M.session_id
I'm able to get the subqueries to work on their own, and results in a list of session_ids, I've tried using where session_id in (subqueries) but that doesn't work. I've also tried doing something like where exists, or left outer join, but I haven't be able to get any of them to work.

After left outer join keep alias name for the all the query you have written to M then run the query again.
Try to run below Query:
select
U.session_id,
U.session_date,
U.email
from data.usage U
left outer join
(select
distinct M.session_id
from data.usage M
where email like '%gmail.com%'
and data_date >= '20180101'
and name in
(
select
lower(name)
from data.users
where role like 'Person%'
and isactive = TRUE
and data_date = '20180412'
))M
on U.session_id = M.session_id

Related

How do I find out which users with a specific RoleID that's not been active within a time interval?

This query down below will tell me how many non-active users there's been during a timeframe.
USE Database
SELECT u.*
FROM [dbo].[tbl_Users] u
WHERE NOT EXISTS (SELECT 1
FROM [dbo].[CaseTable] ct
WHERE c.tUserID = u.UserID AND ct.CreationDate between '2019-01-01' and '2019-12-31'
);
And this query below will tell me the users that have the specific role id I'm looking for.
Use Database;
SELECT UserID, DepartmentID, RoleId
FROM tbl_UsersBelongsTo
WHERE RoleID=6
How can I integrate both queries and essentially get what I'm looking for? I presume it's with a JOIN clause but how??
I think you just want join or additional exists:
SELECT u.*
FROM [dbo].[tbl_Users] u
WHERE NOT EXISTS (SELECT 1
FROM [dbo].[CaseTable] ct
WHERE ct.tUserID = u.UserID AND
ct.CreationDate between '2019-01-01' and '2019-12-31'
) AND
EXISTS (SELECT 1
FROM tbl_UsersBelongsTo ubt
WHERE ubt.RoleID = 6 AND ubt.userId = u.userId
);
Please try to use an inner join like below:
SELECT u.*
FROM [dbo].[tbl_Users] u
INNER JOIN
(
SELECT UserID
FROM tbl_UsersBelongsTo
WHERE RoleID=6
) x ON u.UserID = x.UserID
WHERE NOT EXISTS (SELECT 1
FROM [dbo].[CaseTable] ct
WHERE c.tUserID = u.UserID AND ct.CreationDate between '2019-01-01' and '2019-12-31'
);
You can read more about JOINS here.
If I understood the question correctly - you are using 2 different databases and the name of the 2nd database is pisacara. It is possible to join tables from different databases in SQL Server as long as as those databases are on the same server and you use the same credentials for both databases.
Assuming that tbl_Users table has a UserID field as well, the query would look something like this:
SELECT u.*
FROM [1st_database_name].[dbo].[tbl_Users] u
INNER JOIN [piscara].[dbo].[tbl_UsersBelongsTo] a
ON u.UserID = a.UserID
WHERE NOT EXISTS (SELECT 1
FROM [1st_database_name].[dbo].[CaseTable] ct
WHERE c.tUserID = u.UserID
AND ct.CreationDate BETWEEN'2019-01-01' AND'2019-12-31'
)
AND a.RoleID=6;
You can also try putting the 2nd query in the WHERE clause, as a sub-query, like so:
SELECT u.*
FROM [1st_database_name].[dbo].[tbl_Users] u
WHERE NOT EXISTS (SELECT 1
FROM [1st_database_name].[dbo].[CaseTable] ct
WHERE c.tUserID = u.UserID
AND ct.CreationDate BETWEEN'2019-01-01' AND'2019-12-31'
)
AND u.UserID IN (SELECT UserID
FROM [piscara].[dbo].[tbl_UsersBelongsTo]
WHERE RoleID=6);

combine two query results into one with conditions in SQL Server

I have two query to combine two results into one. However; my challenge is to get the second query look into the first query if it doesn't exist in the first query.
I changed my post to the actual query
SELECT Name.CO_ID, Name.FULL_NAME, Name.ID, rpt.date AS StartDate,
vw_Coords.TARGET_ID AS CoordID, vw_RegDirs.TARGET_ID AS
RDID
FROM Name INNER JOIN
Tops_Profile ON dbo.Name.ID = Tops_Profile.ID left
outer JOIN
vw_mz_rpt_leader_log rpt ON Name.CO_ID = rpt.ID LEFT
OUTER JOIN
vw_RegDirs ON Name.CO_ID = vw_RegDirs.CHAPTER LEFT
OUTER JOIN
vw_Coords ON Name.CO_ID = vw_Coords.CHAPTER LEFT OUTER
JOIN
Tops_Chapter ON Tops_Chapter.ID = Name.CO_ID
WHERE (Name.MEMBER_TYPE = 'm') AND (Tops_Profile.LDR = '1') and
LOG_TEXT like '%LEADER Change%'
union
SELECT Name.CO_ID, Name.FULL_NAME, Name.ID,
YEAR(dbo.Tops_Chapter.PST_DATE_LEAD) AS StartDate,
vw_Coords.TARGET_ID AS CoordID, vw_RegDirs.TARGET_ID AS
RDID
FROM Name INNER JOIN
Tops_Profile ON Name.ID = Tops_Profile.ID left outer
JOIN
vw_mz_rpt_leader_log rpt ON Name.CO_ID = rpt.ID LEFT
OUTER JOIN
vw_RegDirs ON Name.CO_ID = vw_RegDirs.CHAPTER LEFT
OUTER JOIN
vw_Coords ON Name.CO_ID = vw_Coords.CHAPTER LEFT OUTER
JOIN
Tops_Chapter ON Tops_Chapter.ID = Name.CO_ID
WHERE (Name.MEMBER_TYPE = 'm') AND (Tops_Profile.LDR = '1')
the scope is if the record exists in the first query don't bring it from second query.
Here's a quick and dirty way...
select *
from
(select id, Name, log.Date
from Name
inner join Log on Name.id = log.id
where log.text_log like '%Leader%'
union
select id, Name, Profile.Date
from Name
inner join profile on Name.id = profile.id
where profile.Leader = '1') d
order by row_number() over(partition by x.id order by x.Date asc)
Note, this doesn't care where John came from, it's simply finding the first occurrence based on the date which seems to be what you want.
You have altered your request. Suddenly both queries select from the same tables and a UNION (or UNION ALL for that matter) doesn't seem a good solution anymore.
There are very few differences between the two queries even. And looking at the whole it boils down to: select records for member_type = 'm' and tp.ldr = 1 and then keep only one record per name, preferredly one with log_text like '%LEADER Change%'. This is mere ranking, as already shown in my other answer. You only need one query to select all records in question and use TOP (1) WITH TIES to keep the best matches per name.
select top(1) with ties
n.co_id,
n.full_name,
n.id,
case when log_text like '%LEADER Change%' then rpt.date else year(tc.pst_date_lead) end
as startdate,
c.target_id as coordid,
rd.target_id as rdid
from name n
inner join tops_profile tp on n.id = tp.id
left outer join vw_mz_rpt_leader_log rpt on n.co_id = rpt.id
left outer join vw_regdirs rd on n.co_id = rd.chapter
left outer join vw_coords c on n.co_id = c.chapter
left outer join tops_chapter tc on tc.id = n.co_id
where n.member_type = 'm'
and tp.ldr = 1
order by row_number() over (
partition by n.id
order by case when log_text like '%LEADER Change%' then 1 else 2 end);
As you said you just want only one record per name, I am using ROW_NUMBER. If you want more, use RANK instead.
It's not clear why you are joining the tops_chapter table. Is log_text a column in that table? (You should use a table qualifier for this column in your query.) If it isn't, then the join is superfluous and you can remove it from your query.
Use row_number and select id's with least date
with cte as
(select id, Name, log.Date
from Name
inner join Log on Name.id = log.id
where log.text_log like '%Leader%'
union all
select id, Name, Profile.Date as log.date
from Name
inner join profile on Name.id = profile.id
where profile.Leader = '1'
) , ct1 as (select id,name,log.date, ROW_NUMBER() over (partition by id order by log.date) rn from cte )
select id,name,log.date from ct1 where rn = 1
where profile.Leader = '1'
and id not in ( select Name.id
from Name
inner join Log
on Name.id = log.id
where log.text_log like '%Leader%' )
You can use NOT EXISTS in the second query to filter out already existing Name records:
select id, Name, log.Date
from Name
inner join Log on Name.id = log.id
where log.text_log like '%Leader%'
union
select n1.id, n1.Name, Profile.Date
from Name as n1
inner join profile on n1.id = profile.id
where profile.Leader = '1' and
not exists (select 1
from Name as n2
inner join Log on n2.id = Log.id
where Log.text_log like '%Leader%' and
n2.id = n1.id and n2.name = n1.name)
The query below finds logdate and profiledate for each name. If there is a logdate, the logdate will be diplayed else the profile date will be displayed. If both don't exist the Name won't be displayed.
select id, Name, coalesce(log.Date,profile.date)
from Name
left join Log on Name.id = log.id and log.text_log like '%Leader%'
left join profile on Name.id = profile.id and profile.Leader = '1'
where coalesce(log.Date,profile.date) is not null
You can add a rank to your two queries. Then per ID you keep the record(s) with the better rank (using ORDER BY with TOP (1) WITH TIES).
select top(1) with ties
id, name, date
from
(
select n.id, n.name, log.date, 1 as rnk
from name n
inner join log on name.id = log.id
where log.text_log like '%Leader%'
union all
select n.id, n.name, profile.date, 2 as rnk
from name n
inner join profile on name.id = profile.id
where profile.leader = '1'
) data
order by rank() over (partition by id order by rnk);

Oracle Fetching the Result from two Different conditions

I need to get the Values from tables with different conditions for a particular field. For Particular domain id (domain_id) there must be number of usernames assigned different system_id.
For specific system id (123) a column domain (domain_id ) should have the active username only starts with 'a-' 0r 'A-' and all other username should be disabled except the username starts with 'a-' 0r 'A-'.
Please help to get the Expected result ;
The Query I used as below:
SELECT e.domain_id, e.first_name, e.last_name, e.type, e.username,e.system_name
FROM (SELECT p.domain_id, p.first_name,p.last_name,p.type, u.username, u.status, u.system_id ,s.system_name
FROM ur_username u JOIN ur_username_person up ON u.username_id = up.username_id JOIN ur_person p ON up.person_id = p.person_id
JOIN ur_system s ON u.system_id = s.system_id
WHERE u.username LIKE 'A-%' OR username LIKE 'a-%'
AND u.status = 'ACTIVE'
AND u.system_id = 349 ) E
WHERE e.domain_id IN ( SELECT p.domain_id
FROM ur_username u
JOIN ur_username_person up ON u.username_id = up.username_id
JOIN ur_person p ON up.person_id = p.person_id
WHERE u.status = 'DISABLED'
AND u.system_id = 349 )

Postgres hangs when a possible null column value is used in SELECT statement

I'm trying to mash some user data from several tables together in Postgres in order to display information in a table on a web page. Users may or may not have "contact" information, and I'm trying to include the "contact" email address as part of what gets returned in the select query.
The query I'm using boils down to the following:
select u.user_id, r.role_id, u.first_name, u.last_name, c.email, o.state_active, ce.name
from user
join user_role r on u.user_id = r.user_id
join company c on r.company_id = c.company_id
join object_state o on u.state_id = o.state_id
left outer join user_contact uc on u.user_id = uc.user_id and uc.default_flag = 'Y' and uc.status = 'A'
left outer join contact c on uc.contact_id = c.contact_id and c.contact_type like 'E%'
I keep running into problems around the outer joined tables at the bottom. It appears that if I do a SELECT * sort of query, I'll get back everything I expect, but as soon as I run the above query, the statement just hangs and never returns values. If, however, I remove the c.email portion of the select statement, everything returns quickly with no problems at all.
Am I missing some sort of core feature of Postgres where I'm unable to select a column that might be null, or is there something else obvious that I'm completely missing as far as this query goes? I don't understand why it works fine if I don't require the email, but not otherwise.
Could you provide a sqlfiddle with a sample of your database to test our solutions please ?
You can try this :
select u.user_id, r.role_id, u.first_name, u.last_name, COALESCE(c.email,NULL), o.state_active, ce.name
from user
join user_role r on u.user_id = r.user_id
join company c on r.company_id = c.company_id
join object_state o on u.state_id = o.state_id
left outer join user_contact uc on u.user_id = uc.user_id and uc.default_flag = 'Y' and uc.status = 'A'
left outer join contact c on COALESCE(uc.contact_id,-1) = c.contact_id and c.contact_type like 'E%'
Here, you should look at the COALESCE.

Delete statement SQL joins

Can anyone please tell me how to write a delete statement for the following query:
SELECT a.UserID, b.UserEmailAddress
FROM tblUserProgramme AS a LEFT OUTER JOIN
tblUser AS b ON b.UserID = a.UserID LEFT OUTER JOIN
tblWorkGroup AS c ON c.WorkGroupID = b.WorkGroupID
WHERE(a.ProgrammeID = 59) AND (a.UserID NOT IN
(SELECT UserID FROM tblUser AS a WHERE (WorkGroupID IN
(SELECT WorkGroupID FROM tblWorkGroup WHERE
(WorkGroupName LIKE '%Insight%') OR (WorkGroupName LIKE '%Other%')))))
AND (b.UserEmailAddress NOT IN
(SELECT email FROM tmpUsers))
ORDER BY b.UserEmailAddress
SERVER is SQL Server 2005
Query would be
Delete from
(
SELECT a.UserID, b.UserEmailAddress
FROM tblUserProgramme AS a LEFT OUTER JOIN
tblUser AS b ON b.UserID = a.UserID LEFT OUTER JOIN
tblWorkGroup AS c ON c.WorkGroupID = b.WorkGroupID
WHERE(a.ProgrammeID = 59) AND (a.UserID NOT IN
(SELECT UserID FROM tblUser AS a WHERE (WorkGroupID IN
(SELECT WorkGroupID FROM tblWorkGroup WHERE (WorkGroupName LIKE
'%Insight%') OR (WorkGroupName LIKE '%Other%'))))) AND (b.UserEmailAddress NOT IN
(SELECT email FROM tmpUsers))
ORDER BY b.UserEmailAddress
) a
Syntax is DB specific..
For most of tha databases this should work , if you want to delete from tblUserProgramme
DELETE A
FROM tblUserProgramme AS a
.....
In general, in SQL Server, you can delete all records which match a given SQL query as follows, provided your SELECT only returns columns from a single table:
DELETE x
FROM
(
-- Any query which returns data from a single table, that you wish to delete
) x;
Or, using a CTE:
;WITH x as
(
-- Any query which returns data from a single table, that you wish to delete
)
DELETE x;
Thank you all for your quick answers:) There were a quite a few answers right, but had to pick the first one:)
As Joe G Joseph has mentioned,
this is what i did
DELETE a
from dbo.tblUserProgramme a
LEFT OUTER JOIN tblUser b ON b.UserID = a.UserID
LEFT OUTER JOIN tblWorkGroup c ON c.WorkGroupID = b.WorkGroupID
where a.ProgrammeID = 59 AND
a.UserID NOT IN (SELECT UserID FROM tblUser a WHERE a.WorkGroupID IN
(SELECT WorkGroupID FROM tblWorkGroup
WHERE WorkGroupName like '%Insight%' OR WorkGroupName like '%Other%'))
AND b.UserEmailAddress NOT IN(SELECT email FROM tmpUsers)