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

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

Related

Access SQL Lookup - Dropdown Columns

I have looked for a similar issue with no luck. Maybe I don't know the right term to search for.
This seems so simple, but I just can't get it after spending many hours trying different approaches.
I have a dropdown to select contracts which shows some ids for related fields. How can I get those IDs to show the value of another column.
SELECT tbl_contracts.ID, tbl_contracts.contract_name, tbl_contracts.firm_id, tbl_contracts.agency_id
FROM tbl_contracts;
image of dropdown
I would like the IDs shown for agency_id and firm_id to list the company_name from their respective table "tbl_firm_agencies" where the tbl_contracts looks them up from. I've tried INNER JOINS but when I do, I can only line items to show when both agency AND firm exist, so my dropdown get cut off quite a bit.
Simply LEFT JOIN to those lookup tables as opposed to INNER JOIN. Adjust table and field names to actual ones in query below. Also, the parentheses are required in MS Access SQL.
SELECT c.ID, c.contract_name, f.firm_name, a.agency_name
FROM (tbl_contracts c
LEFT JOIN tbl_firms f
ON c.firm_id = f.firm_name)
LEFT JOIN tbl_agencies a
ON c.agency_id = a.agency_name;

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

Refer to different id's within the same query in SQL

I need to brind a lot of columns from several tables using LEFT JOIN. My starting point is the orders table and I bring the vendor name from the "Address_table". Then I add another table with order details and then the shipping information of each order detail.
My problem is that I need to bring a different record from "Address_table" to refer onether id's detailed in shipment table as of "origin_id" and "destination_id".
In other words, "address_id", "origin_id" and "destination_id" are all records from "Address_table". I brought the first one related to the vendor, how can I retrieve the other two?
Example
Thanks in advance
Your question is not exactly clear in terms of the tables and their relationships. It is, however, clear what the problem is. You need to join against the same table twice using different columns.
In order to do that you need to use table aliases. For example, you can do:
select *
from shipment s
left join address_table a on a.address_id = s.origin_id
left join address_table b on b.address_id = s.destination_id
In this example the table address_table is joined twice against the table shipment; the first time we use a as an alias, the second time b. This way you can differentiate how to pick the right columns and make the joins work as you need them to.

UPDATE statement won't update anything

I've been creating a recipe database for a class project using SSMS. I have one table with all the recipe names that I'd inserted into a lookup table (RecipeDetails), but I'd left out their associated IDs, so I wanted to write a bit of code to update my table with those values. I feel like this code should work fine (it seemed to work in the past, but I screwed up something unrelated and had to restore my most recent database backup), but now it just isn't. It says it's affected all the rows I expect it to affect, but those rows still list the RecipeID as NULL.
I'm pulling my data from RecipesTable, which includes the names of each recipe and an ID for each. In RecipeDetails I have a column for RecipeName, RecipeID, Ingredient, IngredientID, and an ID for each row in the table. As of now, I have all my recipes in the table, but not their associated ID. I would like to move the ID's over from one table to another.
UPDATE rd
SET rd.RecipeID = rt.RecipeID
FROM RecipeDetail AS rd
FULL JOIN RecipesTable AS rt ON rd.RecipeID = rt.RecipeID
WHERE rt.RecipeName = rd.RecipeName;
You should use an inner join rather than an outer join.
UPDATE rd
SET rd.RecipeID = rt.RecipeID
FROM RecipeDetail rd JOIN
RecipesTable rt
ON rd.RecipeName = rt.RecipeName;

Microsoft Access joining 4 tables to display specific values from 3 tables but all values from the main table

I have created a database for users to "follow" TV Shows, I need to create a form to display each show and all the relevant information to that specific show.
The four tables I have are as follows:
Shows (Main Table),
Networks,
ShowGenres (Links multiple genre's to one show),
Genres.
The relationships and all fields are shown in the image below.
Currently I have a page which displays the following information:
showID, showName, showAired, networkName, showStatus, showRuntime, showSeasons, showEpisodes, showOverview.
Ideally i'd like to have a List box to display an array of the genre's associated with the specific show. I have tried for quite a while to come up with a query to do this, the closest I managed to get showed the relevant information but added duplicate pages.
Here's my latest attempt:
SELECT * FROM Shows A
INNER JOIN Networks B ON B.networkID = A.networkID
INNER JOIN ShowGenres C ON C.showID = A.showID
INNER JOIN Genres D ON D.genreID = C.genreID;
Any help would be appreciated, thanks in advance.
One has to appreciate the presentation level logic that can be used in conjunction with the data logic. Very generically - in the 1:Many - - your query of fields that include both fields will repeat the 1 table values with each of the Many records. That can not be altered via any query design as it is inherent in the data logic.
But at the presentation level you can control the display. Using a report - the data source can be the query - but report properties offer grouping whereby you can put the 1 field value as the group header - thus displaying just once; and then below it list all the many records.
It is not a list box per se though depending on how creative one gets with reports/sub reports one could potentially make that style. But in the end you must work this at the presentation level.
One method is to use exists:
select g.*
from genres as g
where exists (select 1
from showgenres as sg inner join
shows as s
on sg.showID = s.showID
where sg.genreID = g.genreID and
s.showName = ?
);