SQL - Visual Studio - fill table if related data is empty - sql

In my data source "Properties" is linked to "tenants" and I want to fill a table using a SQL query where tenant does not exist for that property.
In other words, "where that property is vacant."
What is the SQL statement for something like this?
SELECT tblProperties.Type, tblProperties.PropertyID, tblProperties.Street, tblProperties.Unit, tblProperties.City, tblProperties.State, tblProperties.Zip, tblProperties.Description, tblTenant.TenantID
FROM dbo.tblProperties
JOIN tblTenant
ON tblProperties.PropertyID = tblTenant.PropertyID
WHERE tblTenant.TenantID = ''

Properties and Tenants are both tables in your database?
Are they joined by a cross-reference table or...? It would be helpful to see the table structures.
Assuming that's the case, you just want something like:
SELECT * FROM Properties
WHERE PropertyId NOT IN
(SELECT PropertyId FROM PropertyTenants)

Try something like this:
SELECT Property.PropertyID, Property.TenantID
FROM Property LEFT JOIN Tenant ON Property.[TenantID] = Tenant.[TenantID]
WHERE (((Tenant.TenantID) Is Null));
This should show what properties don't have Tenants, Suggest you first try it with JUST the id fields, then add in the other fields later to keep the query simple and help with troubleshooting. If you have the potential to have multiple tenants who have offices in more than one property, this is a many-to-many relationship that is best documented in an index table.

Related

How to check if table relationship is one to many in SSMS

I'm writing some SQL code based on my tables but don't want to miss any edge cases. I'm wondering how do you check if there's a one to many relationship between two tables in SSMS
SELECT *
FROM Houses
JOIN Addresses
on Houses.Id = Addresses.HouseId
Unfortunately the data when queried doesn't give me any insight.
What I tried to do:
Checked table dependencies but that didn't give me any insight. It shows addresses are dependencies but no relationship details.
May I ask, is it possible to determine if one to one via SSMS?
You can run a query to determine how many values each house in the two tables. Well, in this case, we'll assume it is the primary key of houses and the values of HouseId are valid ids:
SELECT num_addresses, COUNT(*)
FROM (SELECT h.Id, COUNT(a.HouseId) as num_addresses
FROM Houses h LEFT JOIN
Addresses a
ON h.Id = a.HouseId
GROUP BY h.Id
) ha
GROUP BY num_addresses;
Then interpret the results:
If the only row returned has num_addresses of 1, then you have a 1-1 relationship.
If two rows are returns with values of 0 and 1, then you have a 1/0-1 relationship.
If multiple rows are returned and the minimum is 1 then you have a 1-n.
If multiple rows are returned and the minimum value is 0, then you have a 0-n.
You could extend this for more general relationships, but this answers the question you asked here.
The relationship between tables is shown by things called 'DATABASE - DIAGRAM'
Here is document about how to create database - diagram in SSMS.
How to create database diagram SSMS
Gordon Linoff response is perfect for the helicopter view -
To get all records side by side simply select all columns from both tables side by side with the left join
SELECT Houses.*, Address.*
FROM Houses
left JOIN Addresses on Addresses.HouseId = Houses.Id
union all
SELECT Houses.*, Address.*
FROM Addresses
left JOIN Houses on Houses.Id = Addresses.HouseId
Microsoft have implemented a reduced code method to do the same but I have not explored it so could not comment
https://learn.microsoft.com/en-us/sql/odbc/reference/develop-app/outer-joins?view=sql-server-ver15
What will be apparent is you will see Houses.ID and Addresses.HouseID side by side - An empty value in either means that the relevant table does not have a record for the relevant HouseID or ID
You can then cherry pick those edge case records as you see fit

Is there a way to select automatically the row pointed by an FK on a given table?

Today while writing one of the many queries that every developer in my company write every day I stumbled upon a question.
The DBMS we are using is Sql Server 2008
Say for example I write a query like this in the usual PERSON - DEPARTMENT db example
select * from person where id = '01'
And this query returns one row:
id name fk_department
01 Joe dp_01
The question is: is there a way (maybe using an addon) to make sql server write and execute a select like this
select * from department where id = 'dp_01'
only by for example clicking with the mouse on the cell containing the fk value (dp_01 in the example query)? Or by right click and selecting something like ("Go to pointed value")?
I hope I didn't wrote something stupid or impossible by definition
Not really, but that seems like a silly thing to do. Why would you want to confuse an id with a department name?
Instead, you could arrange things so you could do:
select p.*
from person p
where department = 'dp_01';
You would do this by adding a computed column department that references a scalar function that looks up the value in the department table. You can read about computed columns here.
However, a computed column would have bad performance characteristics. In particular, it would basically require a full table scan on the person table, even if that is not appropriate.
Another solution is to create a view, v_person that has the additional columns you want. Then you would do:
select p.*
from v_person p
where department = 'dp_01';
Why can't you write yourself by saying
select * from department where id =
(select fk_department from person where id = '01')

What is the correct SQL statement to get the Row Source for a table, based on another field?

I currently have a schema set up in the following manner:
The table tblCategoryRiskArea is set up as an intermediate table for the many-to-many relationship that can exist between Categories and RiskAreas.
Within the tblBase table, I would like to make it so that the RiskArea choices are dependant upon the Category choice. MS Access allows you to set a Lookup for a field in a table based upon a Row Source SQL statement. I am having trouble figuring out the correct SQL statement to define the Row Source for RiskArea dependant upon Category. This:
SELECT tblRiskAreas.RiskAreaID, tblRiskAreas.RiskArea
FROM tblRiskAreas INNER JOIN
((tblCategories INNER JOIN tblBase
ON tblCategories.CategoryId = tblBase.Category)
INNER JOIN tblCategoryRiskArea
ON tblCategories.CategoryId = tblCategoryRiskArea.Category)
ON (tblRiskAreas.RiskAreaID = tblCategoryRiskArea.RiskArea)
AND (tblRiskAreas.RiskAreaID = tblBase.RiskArea)
WHERE (((tblCategoryRiskArea.Category)=[tblBase]![Category]))
ORDER BY tblRiskAreas.RiskAreaID;
is the best I've come up with so far, using MS Access' Query Builder, so all of the Inner Joins have been created just by my having defined the relationships between the tables and dragging them into the Query Builder. This query returns nothing, however.
I suspect that it may have something to do with the circular nature of the relationships I set up?
Thank you.
Edited: tblRiskArea contains 4 RiskAreas, as follows:
Environmental
Health
Safety
Security
Each Category can fall into one or two of these RiskAreas, so the tblCategoryRiskArea creates the relationship bewtween them.
First remove Category and RiskArea from tblBase and replace them for CategoriRiskAreaID
You will show in your form 2 combos. First combo Catagory data source:
Select CategoryId,Category from tblCategories
Second combo Risk Areas data source:
Select a.CategoryRiskId, b.RiskArea
from tblCategoryRiskArea a
inner join tblRiskArea b
where a.RiskAreaId=b.RiskAreaId
AND a.category = #ComboBoxCategorySelectedItem
Now you have the value to insert in tblBase, ComboBoxSelectedItem is tblCategoryRiskArea.CategoryRiskId

MS Access - Linking to record through stored ID

I have a few tables set up in Access as follows (forgive the slightly redundant example content):
Table 1:
- ID
- FirstName
- SecondName
Table 2:
- ID
- Details
- PersonID -> Table 1[ID]
Table 3:
- ID
- Group
- PersonDetails -> Table 2[ID]
Table 1 is the base table containing records and retrieving no other information. For example, it could store someone's first and second names, along with an autonumber ID.
Table 2 contains records which, amongst other things, contain a field that links to Table 1 and stores the ID of one of the records held there. With the lookup wizard I can choose to utilise all fields from Table 1, store the ID of the Table 1 record in the Table 2 field and also display the first and second names in the combobox on the form to make choosing a record more intuitive.
In table 3, I need to store the ID of one of the records in Table 2. However, I would also like to again display in the form combobox the first and second names from the related record (in Table 1) whose ID is stored in Table 2. I can't choose to utilise, for example, the PersonDetails field from table 2 as this just puts ID numbers into the combobox - I'd need to do something equivalent of:
Table 2[ID]->[FirstName]
Is this possible to do with the lookup wizard in Access or would I have to look into queries or VBA?
Thanks.
Your query for your combo should look something like this:
SELECT cp.ID, cp.ReferenceName, c.Company, p.FeePerHour
FROM (ClientProfile AS cp LEFT JOIN Clients AS c ON cp.ClientID = c.ID)
LEFT JOIN Pricing AS p ON cp.PricePlanID = p.ID;
The main problem with your query is that you're missing the Parenthesis that are needed when you have multiple joins. If you had another join, you'd need a second set of parenthesis.
I took some liberty and used table aliases. It makes SQL concise and more readable.
If this query still doesn't work it might be because you're trying to join "child tables" to the "main table" without using your Foreign Key fields as the joining field. If this were my database the SQL would look something like this:
SELECT cp.ClientProfileID, cp.ReferenceName, c.Company, p.FeePerHour
FROM (ClientProfile AS cp LEFT JOIN Clients as C ON cp.ClientID = c.ClientID)
LEFT JOIN Pricing AS p ON cp.ClientProfileID = p.ClientProfileID;
Personally, I basically never use just plain ID as a field name. And when creating a foreign key I usually use the same field name as what the original table has. There are exceptions, especially in the case where you need to link back to the same table more than once. Consider the case where you are tracking real estate properties and you have a Buyer and a Seller that are both entities (but different from each other) in the same People table. You would then need to name them something like BuyerID and SellerID but ultimately they would link back to the PersonID in the Person table.
So Here's the table design I would go for. Notice I changed Group to PriceGroup. Watch out for reserved words when programming, not only in SQL but any language. If you name your field Group at some point you'll be trying to "Group on Group" which sounds and looks bad, if nothing else.
Client:
- ClientID
- FirstName
- SecondName
ClientProfile:
- ClientProfileID
- Details
- ClientID (Foreign Key to Client)
Pricing:
- PricingID
- PriceGroup
- ClientProfileID (Foreign Key to ClientProfile)

MS Access Selecting Related Rows

I have 2 tables with a many-to-any relationship. For the example we will call the tables "Guys" and Girls" There is a junction table that contains the related primary keys...who has dated who.
If I want to find all the girls that Guy 1 has dated, I do a select on the junction table selecting all girls with guys.ID. This give me a RecordSet. Now to find the names of the girls, I need to select from the girls table a row using the key from each RecordSet row.
Isn't there an easier way? Since I've defined the relationships in Access I would think that there must be a way to build a single query. How do I do that?
SELECT girls.name
FROM (guys
INNER JOIN junct ON guys.guyID = junct.guyID)
INNER JOIN girls ON junct.girlID = girls.girlID
WHERE guys.guyID = [whatever id you're looking for]