I have a table structure like this and I am using Postgres
ContactPhoneRelation
id
ContactId
PhoneId
1
123
999
2
123
998
I have another table GroupTable
id
groupId
ContactId
PhoneId
1
1
123
999
2
2
123
999
3
2
123
998
I am trying to fetch the data from ContactPhoneRelation which does not exist in groupId 1 and ContactId is 123, So I want to query such that where groupId is 1 and ContactId is 123 and ContactId phoneId both does not exists in groupId 1
So in return, it should give me this result
id
contactId
PhoneId
2
123
998
If I query for groupId 2, It should give me 0 rows in return.
I tried this query but it gave me the opposite data.
select * from ContactPhoneRelation cp
left join GroupTable gt on gt.ContactId = cp.ContactId
where cp.contactId = '123' and gt.groupId = 1
In all honesty, I don't understand what you are trying to achive. But maybe this is because of language issues.
For better understanding I added an example on db<>fiddle: Link
Edit (29.09.2021; 16:49):
SELECT
c.*
FROM
(
SELECT
b.groupID
,a.ContactID
,a.PhoneID
FROM
(SELECT DISTINCT
ContactId
,PhoneID
FROM
ContactPhoneRelation
) a
FULL JOIN
(SELECT DISTINCT
groupID
FROM
GroupTable
) b ON (1=1)
ORDER BY groupID, ContactID, phoneID
) c
LEFT OUTER JOIN GroupTable d ON (
c.groupID = d.groupID
AND c.ContactID = d.ContactID
AND c.PhoneID = d.PhoneID
)
WHERE
d.groupID IS NULL
Related
I have a TableA:
TeamID PersonID
... ...
1 100
2 101
2 105
2 444
3 501
... ...
Also TableB
PersonID CourseID
... ...
444 c103
444 c2048
101 c3214
... ...
How do I write a simple query such that, for example, I can find whether each person in Team 2 has at least one CourseID associated in TableB. The result for my example is:
TeamID PersonID HasCourse
2 101 1
2 105 0
2 444 1
The shorter the query the better, ideally not using loops.
I would just use case exists:
select a.*,
(case when exists (select 1 from b where b.personid = a.personid)
then 1 else 0
end) as hascourse
from a
where team_id = 2;
Just another method.
select a.TeamID, a.PersonID,
iif(count(b.CourseID)>0,1,0) as HasCourse
from TableA a
left join TableB b on b.PersonID = a.PersonID
where a.TeamID = 2
group by a.TeamID, a.PersonID;
I have three tables in Postgresql, for a biological classification system.
table lang (languages)
id name
1 português
2 english
-------------------------------
table taxon (biological groups)
id name
...
101 Mammalia
-------------------------------
table pop (popular names)
id tax lang pop
...
94 101 1 mamíferos
95 101 2 mammals
I want to get
id name namePT nameEN
101 Mammalia mamíferos mammals
but my join is giving me
id name pop
101 Mammalia mamíferos
101 Mammalia mammals
select t.id,name,pop from taxon t
left join pop p on p.tax = t.id
where t.id = 101
How can I get the desired result in a single row?
If you are happy to change query every time you add a new language then this query will do the trick:
select t.id,name,pe.pop as eng_pop, pp.pop as port_pop
from taxon t
left join pop pe on pe.tax = t.id and pe.lang = 1
left join pop pp on pp.tax = t.id and pp.lang = 2
where t.id = 101
You could use this
SELECT t.id, t.name,
MAX(CASE WHEN p.lang = 1 THEN p.pop END) AS namePT,
MAX(CASE WHEN p.lang = 2 THEN p.pop END) AS nameEN
FROM taxon t
LEFT JOIN pop p
ON p.tax = t.id
GROUP BY t.id, t.name;
Here's how I got the results:
with base as (
select t.id, t.name,
case when lang = 1 then 'mamiferos' else null end as namePT,
case when lang = 2 then 'mamals' else null end as nameEN
from taxon t
left join pop p on t.id = p.tax
group by 1,2,3, p.lang
)
select
distinct id,
name,
coalesce(namept,'mamiferos',null) as namept,
coalesce(nameen,'mamals',null) as nameen
from base
where id = 101
group by id, name, namept, nameen;
id | name | namept | nameen
-----+----------+-----------+--------
101 | Mammalia | mamiferos | mamals
(1 row)
I'm trying to build a query to give me some information doing an inner join on two tables, tableA and tableB. Here's what they look like:
TableA:
ClientID RevNo RevPurp
------------------------------
123 4557 1
124 4555 1
123 6574 2
123 7857 3
124 8987 2
TableB:
RevNo ClientID Active
------------------- -------------
4557 123 True
6574 123 True
7857 123 True
8987 124 True
4555 124 True
Here is what I'm trying to do. I'm trying to do...
Select Distinct ClientID
From TableB
Inner Join TableA On tableB.RevNo = tblB.RevNo
Where RevPurp is not 3.
RevPurp can be 1,2,3 - I'm only trying to select those distinct clients that can have either 1,2 but cannot have a 3.
Looking at the data in the table I should only have 1 record....
124
Because client 123 has RevPurp 3. So if a client has RevPurp 3, I do not want to see that client when I execute the query!
EDIT - I added a field in TableB called ACTIVE. I need to make sure Active = True when doing my query!
as #devlin mentioned in a comment, you do not need tableB to do this:
You want a list of unique (distinct) ClientIds in TableA where there is no record in tableA with a RevPurp value of 3.
EDIT: adding in the filter predicate on TableB.Active
Select distinct a.ClientId
from tableA a join tableb b
on b.RevNo = a.RevNo
Where b.Active = 1 -- <===== is Active a BIT field
and Not exists
(Select * from tableA
Where ClientId = a.ClientId
and RevPurp = 3)
You can try not in
Select Distinct ClientID
from TableB
inner join TableA on tableB.RevNo = tblB.RevNo
where tableA.ClientID not in (select ClienID from tableA where RevPurp = 3)
A simple group by with a having clause should work:
select clientId
from tableA
group by clientId
having count(*) = count(case when RevPurp <> 3 then 'X' end)
I have a contact table and contactphone tables.
Each record in contacts can have many records in contactphone but only 1 can be primary at most (primary is Boolean but can be also NULL)
Contacts:
cid name address
1 Jack A
2 Bill B
3 Mor C
4 Jeff D
ContactsPhones:
cpid cid phone primary
1 1 140 True
2 1 150
3 2 170
I need to write a query that returns all contacts with their details, if they have more than 1 phone then present only primary.
Output:
cid name address phone
1 Jack A 140
2 Bill B 170
3 Mor C
4 Jeff D
What is most easiest way to do it?
Note that primary can have (True,False, Null)
This is a bit tricky. I think the easiest method is distinct on:
SELECT DISTINCT ON (cid) cid, name, address, cp.phone
FROM Contacts c LEFT JOIN
ContactsPhones cp
ON c.cid = cp.cpid
ORDER BY cid, (case when primary then 1 else 2 end);
You can use a LEFT JOIN to a derived table that uses ROW_NUMBER to specify more suitable record:
SELECT cid, name, address, phone
FROM Contacts AS c
LEFT JOIN (
SELECT phone, cpid,
ROW_NUMBER() OVER(PARTITION BY cpid
ORDER BY CASE
WHEN primary THEN 0
ELSE 1
END) AS rn
FROM ContactsPhones) AS cp
ON c.cid = cp.cpid AND cp.rn = 1
someone please help me with this query,
i have 2 tables
Employee
EmployeeID LanguageID
1 1
1 2
1 3
2 1
2 3
3 1
3 2
4 1
4 2
4 3
Task
TaskID LanguageID LangaugeRequired
1 1 1
1 2 0
2 1 1
2 2 1
2 3 1
3 2 0
3 3 1
LangaugeID is connected to table langauge (this table is for explaination only)
LangaugeID LanguageName
1 English
2 French
3 Italian
is there a possilbe way to make a query which gets employees where they can speak all the languages required for each task?
for example:
Task ID 1 requires only LanguageID = 1, so the result should be EmployeeID 1,2,3,4
Task ID 2 requires all 3 languages, so the result should be EmployeeID 1,4
Task ID 3 requires only LanguageID = 3, so the result should be EmployeeID 1,2,4
here is another variant to do this:
select t1.taskid, t2.employeeid from
(
select a.taskid, count(distinct a.languageid) as lang_cnt
from
task as a
where a.LangaugeRequired=1
group by a.taskid
) as t1
left outer join
(
select a.taskid, b.employeeid, count(distinct b.languageid) as lang_cnt
from
task as a
inner join
employee as b
on (a.LangaugeRequired=1 and a.languageid=b.languageid)
group by a.taskid, b.employeeid
) as t2
on (t1.taskid=t2.taskid and t1.lang_cnt=t2.lang_cnt)
###
here you can insert where statement, like:
where t1.taskid=1 and t2.employeeid=1
if such query returns row - this employee can work with this task, if no rows - no
###
order by t1.taskid, t2.employeeid
as you see, this query creates two temporary tables and then joins them.
first table (t1) calculates how many languages are required for each task
second table (t2) finds all employees who has at least 1 language required for task, groups by task/employee to find how many languages can be taken by this employee
the main query performs LEFT JOIN, as there can be situations when no employees can perform task
here is the output:
task employee
1 1
1 2
1 3
1 4
2 1
2 4
3 1
3 2
3 4
update: simpler, but less correct variant, because it will not return tasks without possible employees
select a.taskid, b.employeeid, count(distinct b.languageid) as lang_cnt
from
task as a
inner join
employee as b
on (a.LangaugeRequired=1 and a.languageid=b.languageid)
group by a.taskid, b.employeeid
having count(distinct b.languageid) = (select count(distinct c.languageid) from task as c where c.LangaugeRequired=1 and c.taskid=a.taskid)
Another version using NOT EXISTS
Retrieve all task-employee combinations where a missing language does not exist
SELECT t1.EmployeeId, t2.TaskId
FROM (
SELECT DISTINCT EmployeeID
FROM Employee
) t1 , (
SELECT DISTINCT TaskID
FROM Task
) t2
WHERE NOT EXISTS (
SELECT 1 FROM Task t
LEFT JOIN Employee e
ON e.EmployeeID = t1.EmployeeID
AND e.LanguageID = t.LanguageID
WHERE t.TaskID = t2.TaskID
AND LanguageRequired = 1
AND e.EmployeeID IS NULL
)
http://www.sqlfiddle.com/#!6/e3c78/1
You could use a Join logic to get the result, something like:
SELECT a.EmployeeID FROM Employee a, Task b WHERE b.LanguageRequired == a.LanguageID;