Databindings.Add() joined tabels with duplicate field names - vb.net

I have two tables (Person and Company). Both tables have a field 'Id' (e.g. Person.Id and Company.Id) and the tables are joined on Person.CompanyId = Company.Id
When using DataBindings.Add() to a textbox for example - using WinForms and VB .Net - I would like to use method suggested by Microsoft namely:
txtPersonId.DataBindings.Add("Text", objDataView, "Person.Id")
txtCompanyId.DataBindings.Add("Text", objDataView, "Company.Id")
In this case, I get the following error however: "Child list for field Person cannot be created". After some fiddling around, it looks like 'Person' is looked up as a field in objDataSet instead of 'Person.Id'.
After I change the SQL query and have Person.Id returned as the alias 'PersonId' and Company.Id as 'CompanyId' the following code does work:
txtPersonId.DataBindings.Add("Text", objDataView, "PersonId")
txtCompanyId.DataBindings.Add("Text", objDataView, "CompanyId")
My question is therefor: Why is the Microsoft example not working here (see example here) and how can one include the table name in a DataBindings.Add() method otherwise?

Related

MS Access SQL, sort by age in a specific order

My task: "Compile an SQL query that outputs a specific store (enter parameter window) the age of the youngest buyer"
I´ve tried some things, but because i´m new to SQL and i have no idea what i´m doing non of them seem to work.
I´d really appreciate, if someone would help me.
Thanks!
First you need to know the fields to SELECT (or return) and the table FROM which you are querying (asking) data; let's say you have the following tables: tblStores (containing a list of stores and related info), tblCustomers (containing customers and related info, e.g. ages, names, phone numbers, etc.), and tblPurchases (containing all the purchases at all stores by all customers and related info). You want the minimum age of a customer making a purchase at a specfic store, so you could use a MIN aggregating function. You would want to join (or relate) the tables based on customers and purchases. See my INNER JOINs in the example below. Then you filter the result by the user-inputted store name (inputStoreName) using WHERE; since the inputStoreName is undefined, in Access this would cause the parameter entry popup window to appear.
SELECT list of fields or aggregating functions you want (comma-separated)
FROM list of tables the fields are in (comma-separated) and how to join the tables
WHERE list of conditions to filter the data (separated by AND or OR)
Example:
SELECT tblStores.Name, tblStores.Description, MIN(tblCustomers.age)
FROM tblStores INNER JOIN ( tblPurchases INNER JOIN tblCustomers on tblPurchases.customerID = tblCustomer.customerID) ON tblStores.storeID = tblPurchases.storeID
WHERE (tblStores.Name = inputStoreName);
I recommend checking W3 schools. They are usually helpful for most programming tasks. If you provide more info about your database, we can provide more directed help.

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)

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

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.

MS Access Subquery that returns Multiple Fields

So im back again with more MS Access problems. I have a INSERT INTO query with a subquery that checks to see if the data already exists.
SELECT name, course
FROM foo
WHERE (name, course) NOT IN (SELECT name, course FROM bar);
to expound a little on what i am trying to accomplish since the above doesn't work.
I am trying to select composite keys that do not exist already in the table bar. For example the following could be stored in the table bar:
"John Doe" , "Calc 101"
"John Doe" , "English"
"Jane Doe" , "Calc 101"
And the following could be in the table foo:
"John Doe", "Calc 101"
"John Doe", "Science"
The query should return the following:
"John Doe", "Science"
Everywhere i have looked says the above will work and im sure it does in theory. The problem i run into is with MS Access... When i attempt to run this query it pops up stating that the subquery will return multiple fields. Indeed it should as that is what i want it do do is return 2 fields that i can compare the other 2 fields. The above 2 fields are a composite key in my "bar" database.
For more background I am using MS Excel 2007 and MS Access 2007. The Excel is being used to input data and running the query through VB script. I am trying to make a subquery that checks for fields already in the final database because i ran into the error of MS Access opening up and spitting out a ERROR message about appending primary keys and closes with out executing the query. <-- That is to be expected due to the composite key.
Use LEFT JOIN and look for NULL values:
SELECT bar.name, bar.course
FROM bar LEFT JOIN foo ON bar.name = foo.name AND bar.course = foo.course
WHERE foo.name IS NULL
I've updated the SQLFiddle to include the INSERT followed by a SELECT to show the final table. I've also added composite primary keys to both tables so you can see that you do not get any duplicate inserts.
your sub query is returning two columns. make it return one. If want a where clause that can be in two columns, use OR
SELECT name, course
FROM foo
WHERE (name) NOT IN (SELECT name FROM bar) and (course)
NOT IN (SELECT course FROM bar);
Edit:
Your problem stems from a normalization issue. A suggested redesign would be to have a table for students and a table for courses and a table to join them. Example:
**StudentTable**
studentId(int PK)
firtName(string)
lastName(string)
**ClassTable**
classId(int PK)
ClassName
ClassDesc
**classTable_studentTable**
studentClassID
studentID
classID
Each student can have many classes and each class can have many students. It's a many to many relationship that is normalized by using the join table.
Now, if you wanted to do a query like your asking:
Select *.student, *.class
from
studentTable as student,
classTable as class
where
student.name<>'allen' and class.name<>'math'

SQL: Proper Join Syntax

Suppose I have two tables, one with blog posts and another with readers and their comments:
Table 1:
table name: BlogPosts:
structure:
id (int)
title (string)
Table 2:
table name: Readers:
id (int)
blog_post_id (int)
name (string)
comment (string)
in the Readers table there is a unique composite key on blog_post_id/name (i.e. one comment per reader per post), though this may not matter for my question.
I want to be able to do a single query tells me what a particular reader's comment was on each BlogPost, but it should include BlogPosts for which there is no comment entered for that reader (so the query should return one row for each blog post in the database).
I tried several variations that look like this:
SELECT
BlogPosts.id,
BlogPosts.title,
Readers.name,
Readers.comment
FROM
BlogPosts
RIGHT JOIN Readers ON
(BlogPosts.id = Readers.blog_post_id)
WHERE Readers.name = "joe"
..this just returns the rows where there is actually a comment from joe. Other variations where I was able to get all of the blog posts gave me an invalid identifier whenever I included the where clause.
I am using Oracle Express 10g in case that makes any difference.
Thanks for any help.
Everything looks correct except that you want to move the WHERE clause into the join, like this:
SELECT BlogPosts.id,
BlogPosts.title,
Readers.name,
Readers.comment
FROM BlogPosts
RIGHT JOIN Readers ON BlogPosts.id = Readers.blog_post_id
AND Readers.name = 'joe'
You effectively make the OUTER JOIN into an INNER one when you put the Readers.name = 'joe' in the WHERE clause.
Edit:
Thanks to the OP for clarification in the comments.
What you describe in your most recent comment can be achieved simply by switching from a RIGHT JOIN to a LEFT JOIN (as suggested earlier on by another commenter).
Note that you can get more than one row per BlogPost when there are multiple comments per post.