Access: Inner join query not producing results - sql

I'm trying to perform a query (using Access 2010) on the following tables:
Contact | Facility_Contact | Facility | Bank
| | |
ID | (fk) Contact_ID | ID | ID
CName | (fk) Facility_ID | FName | BName
| | BNumber | BNumber
I would like the final result to display:
CName | FName | BName
Here is the query:
SELECT
HUD.[HOLDER NAME], Facility.PROVNAME, Contact.LAST_NAME
FROM
Facility INNER JOIN Bank ON Facility.[BNumber] = Bank.[BNumber]) INNER JOIN
(Contact INNER JOIN Facility_Contact ON Contact.[ID] = Facility_Contact.[Contact_ID]) ON Facility.[ID] = Facility_Contact.[Facility_ID];
This doesn't produce any results.
The problem comes up when I add the "Bank" table. Queries from Contact to Facility work, as do queries from Facility to Bank. However I'm having difficulty producing results when trying to link from Contact to Bank.
Maybe a Where-like clause somewhere? But now I'm speaking of things that I'm not too familiar with ;)
Thank you all!

FROM
Facility INNER JOIN Bank ON Facility.[BNumber] = HUD.[BNumber])
You close a paranthetical but never open it. Although that would result in an error, so I assume that is a typo.
Facility INNER JOIN Bank ON Facility.[BNumber] = HUD.[BNumber]
You are joining Facility with Bank but then in your ON clause you state that Facility.[BNumber] = HUD.[BNumber] Where did HUD come from? This is not good.
Facility INNER JOIN Bank ON Facility.[BNumber] = HUD.[BNumber]) INNER JOIN (Contact INNER JOIN Facility_Contact ON Contact.[ID] = Facility_Contact.[Contact_ID]) ON Facility.[ID] = Facility_Contact.[Facility_ID];
Your schema appears to be Facility->Bank; Facility->Facility_contact->Contact. Consider rewriting to reflect this (This is just for readability):
FROM
Facility
INNER JOIN Bank ON Facility.[BNumber] = Bank.[BNumber]
INNER JOIN Facility_Contact ON Facility.[ID] = Facility_Contact.[Facility_ID]
INNER JOIN Contact ON Facility_Contact.[Contact_ID] = Contact.[ID]
Now to get records returned all of those joins need contain data. There needs to be a matching BNUMBER in your Bank table for each BNumber in Facility table. There needs to be a matching facility_id in your Facility_Contact table for each ID in your Facility. There needs to be a matching ID in your Contact table for each Contact_ID in your Facility_Contact table. If any of these links are missing you will get 0 records. If you want to show Facilties and Bank Names regardless if they have a Facility Contact then consider using a LEFT JOIN instead:
FROM
Facility
INNER JOIN Bank ON Facility.[BNumber] = Bank.[BNumber]
LEFT JOIN Facility_Contact ON Facility.[ID] = Facility_Contact.[Facility_ID]
LEFT JOIN Contact ON Contact.[ID] = Facility_Contact.[Contact_ID]
This won't drop results just because you don't have a contact at the facility yet. Or that contact hasn't been set up in the Contact table.

Related

Marketing Cloud SQL: Find record that was actioned most recently to the closedate of a record on a different table

I'm needing to write a query that finds all opportunities on an account that closed within 90 days of an email record being clicked by a contact on the account.
My resulting table is currently displaying multiple rows for a given opportunity, because the client and their spouse may have received multiple emails that were clicked that marketed the opportunity.
I want to show a unique opportunity id and on the same row, display the email that was most recently clicked compared to the closedate.
Current query:
select o.id,
o.accountid,
o.CloseDate,
c.id,
e.Name,
e.et4ae5__DateOpened__c
from Opportunity_Salesforce o
inner join Account_Salesforce a
on o.accountid = a.id
left join Contact_Salesforce c
on c.accountid = a.id
inner join et4ae5__IndividualEmailResult__c_Salesforce e
on e.et4ae5__Contact__c = c.id
where ((e.Name like 'xyz%'
OR e.Name like 'abc%'
OR e.Name like 'etc%')
and e.et4ae5__Opened__c = 'true')
and (o.iswon = 'true'
and o.closedate < dateadd(day, 91, et4ae5__DateOpened__c)
and o.closedate >= et4ae5__DateOpened__c)
Edit:
Schema
et4ae5__IndividualEmailResult__c_Salesforce relates to contact on e.et4ae5__Contact__c = c.id
et4ae5__IndividualEmailResult__c_Salesforce does not relate to account or opportunity
Contact_Salesforce relates to Account_Salesforce on c.accountid = a.id
Contact_Salesforce may or may not relate to the opportunity record I want to find, so I'm not relating them. I suppose I could do c.accountid = o.accountid
Opportunity_Salesforce relates to the Account_Salesforce on o.accountid = a.id
Here's a sample of the resulting database where there's a duplicate opportunity found because there are two associated email results:
Opp ID|Account ID|Contact ID|Email Name|Opened|Open Date|Close Date
123 | 1234 | 1234|Buy This 1| TRUE | 5/27/22| 6/9/22
123 | 1234 | 2345|Buy This 1| TRUE | 6/1/22| 6/9/22
Where in the output, I'd want to see the second record instead of the first because it was opened more recently to the close date

Postgres join and count multiple relational tables

I want to join the 2 tables to the first table and group by a vendor name. I have three tables listed below.
Vendors Table
| id | name
|:-----------|------------:|
| test-id | Vendor Name |
VendorOrders Table
| id | VendorId | Details | isActive(Boolean)| price |
|:-----------|------------:|:------------:| -----------------| --------
| random-id | test-id | Sample test | TRUE | 5000
OrdersIssues Table
| id | VendorOrderId| Details. |
|:-----------|--------------:-----------:|
| order-id | random-id | Sample test|
The expected output is to count how many orders belong to a vendor and how many issues belongs to a vendor order.
I have the below code but it's not giving the right output.
SELECT "vendors"."name" as "vendorName",
COUNT("vendorOrders".id) as allOrders,
COUNT("orderIssues".id) as allIssues
FROM "vendors"
LEFT OUTER JOIN "vendorOrders" ON "vendors".id = "vendorOrders"."vendorId"
LEFT OUTER JOIN "orderIssues" ON "orderIssues"."vendorOrderId" = "vendorOrders"."id"
GROUP BY "vendors".id;```
You need the keyword DISTINCT, at least for allOrders:
SELECT v.name vendorName,
COUNT(DISTINCT vo.id) allOrders,
COUNT(DISTINCT oi.id) allIssues
FROM vendors v
LEFT OUTER JOIN vendorOrders vo ON v.id = vo.vendorId
LEFT OUTER JOIN orderIssues oi ON oi.vendorOrderId = vo.id
GROUP BY v.id, v.name;
Consider using aliases instead of full table names to make the code shorter and more readable.
You are joining along two related dimensions. The overall number of rows is the number of issues. But to get the number of orders, you need a distinct count:
SELECT v.*, count(distinct vo.id) as num_orders,
COUNT(oi.vendororderid) as num_issues
FROM vendors v LEFT JOIN
vendorOrders vo
ON v.id = vo.vendorId LEFT JOIN
orderIssues oi
ON oi.vendorOrderId = vo.id
GROUP BY v.id;
Notes:
Table aliases make the query easier to write and to read.
Quoting column and table names makes the query harder to write and read. Don't quote identifiers (you may need to recreate the tables).
Postgres support SELECT v.* . . . GROUP BY v.id assuming that the id is the primary key (actually, it only needs to be unique). This seems like a reasonable assumption.

Subquery to extract values from 4 tables

Some people told me this is not a very difficult one but unfortunately I can't really figure it out. I have the following tables
Person
**ID_Pers** | PersName | City | State | Phone | Email
1950901123893 Michael Houston Texas --- ----
Student
**ID_student** | *ID_Pers* | entry_year | status | exit_year
A123 1950901123893 2014 finished 2017
Subject
**ID_subject** | Subject_name | credit_number | courses | laboratories
Exams
*ID_student* | *ID_subject* | **exam_date** | final_grade
The bold ones are primary keys while the ones that are italicized are foreign keys. I have to extract the students that have passed at least the exams that Michael has passed. I know I have to use subqueries in which I first select the exams that Michael has passed, then select the students that have passed those exams at least. I am having difficulties with this assignment. Can anyone assist me, please?
SELECT * from Exams
INNER JOIN student ON student.ID_student = exams.ID_student
INNER JOIN person ON student.ID_Pers = person.ID_pers
WHERE exams.final_grade >=5 AND person.PersName = "Michael"
I know this is to basically select the exams that Michael has passed. But I need something before it to extract the other people which have passed at least the ones he passed.
You can fetch all the students that have passed the Exams (any exams) and then JOIN the result with the exams fetched in your query. Your final Query should look something like this:
SELECT * from Exams A
INNER JOIN student ON student.ID_student = exams.ID_student
INNER JOIN person ON student.ID_Pers = person.ID_pers
INNER JOIN
(SELECT * from Exams
INNER JOIN student ON student.ID_student = exams.ID_student
INNER JOIN person ON student.ID_Pers = person.ID_pers
WHERE Exams.final_grade >=5 AND person.PersName = "Michael") B ON A.ID_Subject = B.ID_Subject AND A.exam_date = B.exam_date
WHERE A.final_grade >=5;
Hope this helps!

SQL Self Join + Another Join Not working

I've got two tables, Job and User, and am trying to pull together some records. Job needs to be joined with User, and User to itself. The structure is:
JobID | OwnerID | ClientName
1 | 1 | Corey
-----------------------------
UserID | ManagerID | Name | Email
1 | 2 | Jon Smith | job#test.com
2 | | Jane Doe | jane#test.com
I'm looking to obtain a table that contains the manager's email address, in addition to the user's name. My query is:
SELECT
Job.ClientName as 'ClientName',
U1.Name as 'SalesPersonName',
U2.Email as 'ManagerEmail'
FROM
Job
INNER JOIN User U1 ON Job.OwnerID = U1.UserID
INNER JOIN User U2 ON U1.UserID = U2.ManagerID
WHERE
Job.ID = '1'
This pulls all Job data, and all data for U1...but is failing to populate U2 - the manager's information.
I imagine I've got something messed up with the self-join. The query validates, so I'm at a loss for what it is.
Any guidance is greatly appreciated.
Note: the above table/column names have been simplified to protect the innocent.
It looks like you juxtaposed the table aliases on the fields in your last JOIN:
This: FULL JOIN User U2 ON U1.UserID = U2.ManagerID
Should be this: FULL JOIN User U2 ON U2.UserID = U1.ManagerID
Full query:
SELECT
Job.ClientName as 'ClientName',
U1.Name as 'SalesPersonName',
U2.Email as 'ManagerEmail'
FROM
Job
FULL JOIN User U1 ON Job.OwnerID = U1.UserID
FULL JOIN User U2 ON U2.UserID = U1.ManagerID
WHERE
Job.ID = 1 --removed ticks here, assuming int column
Note: You don't need a FULL JOIN unless there are records that won't join together, and you want to preserve those records with NULL values in your result set. For the example provided, a basic INNER JOIN would work, but maybe you need the FULL JOIN for your true data set so I left it in.
Note 2: user is a reserved word in many DBMS and could cause you headaches if used as a tablename

SQL Joins with 4 tables

I have a problem here and I got a bit confused with outer/inner joins and multiple conditions
We have 4 tables with - columns:
table_cars - id | brand | type | license
table_equipments - id | name | description
table_distances - id_car | date | distance
table_cars_equipments - id_car | id_equipment
First query should show all cars that have equipment "fire extinguisher" and have been driving yesterday.
I have tried to write this query:
SELECT table_cars_equipments.id_car
FROM table_equipments
INNER JOIN table_cars_equipments
ON table_equipments.id = table_cars_equipments.id_equipment
AND table_equipments.name LIKE 'fire extinguisher';
Though I am still confused how to add the cars which had been driving yesterday, I don't know how to make the connection with the table table_distances.
Add another JOIN with the table table_cars and another one to the table table_distances. Then add a condition to the WHERE clause to get only those cars that have been driving yesterday. Something like this:
SELECT
c.id,
c.brand,
c.type,
c.license
ce.id_car,
...
from table_equipments AS e
INNER JOIN table_cars_equipments AS ce ON e.id = ec.id_equipment
INNER JOIN table_cars AS c ON c.id = ce.id_car
INNER JOIN table_distances AS d ON d.id_car = c.id
WHERE e.name LIKE 'fire extinguisher'
AND d.date = ?;
Note that: I used aliases for the table c, e etc, instead of the tables' full names.