ms access table relationships - where clause - ms-access

I have two tables that I'm trying to create a relationship for.
Table_A:
ID_A
Flag (Y/N)
Table_B:
ID_A
ID_B
The two tables link on ID_A, where Table_A.Flag='Y'
Is there a way to define the relationship in this way?
Clarification:
I am using the fact that it can be done in SQL as the basis for my question--how would I translate this into a ms-access table relationship?

Whilst this is certainly possible when constructing Queries in MS Access, as far as I'm aware, it isn't possible to define a Table Relationship as anything more advanced than either an INNER or (RIGHT/LEFT) OUTER join, with or without Referential Integrity.

Access (JET) SQL will not let you join on a condition like you can in other variants such as T-SQL. So you can't do the following:
ON a.ID = b.ID
AND Flag = 'y'
The way I'd probably solve this problem in Access-SQL would be to create a subquery by editing the SQL like this:
SELECT *
FROM (SELECT * FROM Table_A WHERE Flag = 'y') a
INNER JOIN Table_B b
ON a.ID = b.ID
Or else by materializing the "SELECT * FROM Table_A WHERE Flag = 'y'" as an Access query and joining to it.

Related

Database Tables with possible Join Candidates

Let's say I have some db tables created in SQL Server, those could be named Table1, Table2, Table3, Table4 and Table5 (but could be more).
Now, what I want to achieve is to possibly mark the columns in those tables that could possibly indicate a candidate I could use for joining the tables.
Is this possible somehow with SQL? Or is there any SW Tool which could create a database model upon the data/tables which would join the tables with same column names?
Example could be with Business Intelligence table structures: I could have 5 tables and wanted to decide which dimension is shared for fact tables etc.
You could view all the columns with a certain piece of text in it, such as "%ID"
Use this script:
SELECT t.name As TableName, c.name AS ColumnName
FROM sys.tables AS t
INNER JOIN sys.columns AS c
ON t.[object_id] = c.[object_id]
WHERE c.name Like ('%ID') --You can change ID to anything you need
AND t.is_ms_shipped = 0
AND t.name NOT LIKE '#%';
A similar question was posted here: How to select column names from multiple tables in SQL Server 2000-2008 that are in a set of names

SQL Join vs Where

Lets say we have following two tables:
A (id, name, type)
B (id, A_id, data)
Hence from above
A has_many B (foreign_key : A_id)
Now can we say following that
if B is not indexed on A_id then B INNER JOIN A will be slow ?
Also lets assume that we know that
SELECT * FROM B WHERE B.A_id = 100
takes x seconds.
Can we make any conclusion on how much time INNER-JOIN will take based on this ?
I imagine the exact timings might depend on the DBMS being used, but it'll probably be negligible.
In theory they should have a very similar performance, exact timing would be difficult to discern due to the many uncertainties involved: number of processes running, etc.
If you're using oracle you could try EXPLAIN PLAN if you're using oracle, other DBMS have similar systems.
The execution plan for a join would look like this:
SELECT * FROM A
INNER JOIN A ON A.id = B.id;
-- 0 select statement
-- 1 hash join (access("A"."ID"="B"."ID"))
-- 2 table access full A
-- 3 table access full B
The execution plan for a where would look like this:
SELECT * FROM A, B
WHERE A.id = B.id;
-- 0 select statement
-- 1 hash join (access("A"."ID"="B"."ID"))
-- 2 table access full A
-- 3 table access full B
They should have a very similar performance, JOIN is an ANSI standard, it is easy to read and can easily be changed to OUTER JOIN/LEFT JOIN/RIGHT JOIN, I suggest you should always use a JOIN over a WHERE

mysql : Can I recreate a table using select, innerjoin and where clause in a single step?

I am new to using mysql workbench, and really need a simple data extraction script (post which I will be back in the land of the free i.e. python)
The idea is to create a new table by joining two pre-existing tables on an id, and applying a where clause. IS the following alright? or do I need to first apply the where clause and then do the create and join?
Here is attempt number 1 (which did not work).
CREATE TABLE `mysql`.`new_tbl`(
SELECT a.* , b.*
FROM mysql.tbla a INNER JOIN mysql.tblb b
ON a.id = b.id
where b.category='Z'
);
You can use views, I think it most approaches what you're idealizing.
You'll find syntax details here.
For your specific situation, you shall run
CREATE OR REPLACE VIEW view_name AS
SELECT a.*, b.* FROM mysql.tbla AS a
INNER JOIN mysql.tblb AS b
ON (a.id = b.id)
WHERE b.category = 'Z';

How to make Table Joins in PHPmyAdmin

I have 2 Tables in phpmyadmin that need joining
tracklisting is my one and catelogue is the other, and are saved as innodb
They both have a column CAT.NO and would like it to be joined on this column. In catelogue it is the primary and in tracklisting it's indexed
catelogue is my parent and tracklisting would be the child as it doesn't have info for every record in catelogue. I believe this would be correct unless I'm wrong
How do I do this so that when I query on a column in tracklisting it only brings up the matches for 'catelogue' because I want to know what album it's on and not my entire 60000+ catelogue
Can this be done with phpmyadmin's interface or is this a sql statement
Many thanks
EDIT:
This was the code that worked
SELECT *
FROM tracklisting
INNER JOIN catelogue ON catelogue.`CAT NO.` = tracklisting.`TRACKLISTING CAT NO.`
WHERE tracklisting.`ARTIST` LIKE 'placebo'
Thanks to everyone that helped out
I dont know if this can be done with the interface, but with sql
SELECT *
FROM
tracklisting t
INNER JOIN catelouge c on c.catno=t.catno
WHERE t.id = 1
You can query with a LEFT JOIN:
SELECT * FROM tracklisting LEFT JOIN catelogue ON tracklisting.`CAT.NO` = catelogue.`CAT.NO` WHERE tracklisting.`<id-field>` = <id-value>`
http://dev.mysql.com/doc/refman/5.0/en/join.html
Assuming that your tracklisting has an id and you want to query with it:
select * from tracklisting t
inner join catelogue c on c.cat.no = t.cat.no
where t.id = 1
The actual join takes place in a SQL statement although with certain storage types like InnoDB you can also create foreign key references that enforce the relationship at the database level so that your inserts require the proper records to be in place and your deletes are restricted if child records exist.
Here is one way of doing the join syntax for your SQL query:
SELECT t.* FROM tracklisting t, catalogue c
WHERE `t.CAT.NO` = `c.CAT.NO`
EDIT: Here is a link to a tutorial for creating foreign keys in phpMyAdmin.

MS Access Inner Join doesn't recognize difference between small and capital letters?

As title says, this issue happens in MS Access 2003 SP1. Does anyone know what could be solution for this problem?
Pseudo query
select * from a inner join b on a.id=b.id
For small data sets, there are any number of approaches using various possible string conversions.
But if your data sets are of any size at all, this will be very slow because it can't use the indexes.
You could possibly optimize by joining case insensitively and then using criteria to test whether the case is the same, e.g.:
SELECT *
FROM a INNER JOIN b ON a.id=b.id
WHERE Asc(a.id) <> Asc(b.id)
This would at least allow the use of an index join so you wouldn't be comparing "a" to "b" and "a" to "c" (as would be the case with joining on string functions), but only "a" to "a" and "a" to "A".
I would suggest that if your data really needs to distinguish case, then you probably need to store it in a database engine that can distinguish case in joins and then pass your SQL off from Access to that database engine (with a passthrough query, for example).
EDIT:
#apenwarr suggests using StrComp() in the JOIN (as did #butterchicken yesterday), and this SQL raises a question for me (I've updated her/his SQL to use the same table and fieldnames I use above; it's essentially the same as #butterchicken's SQL)
SELECT *
FROM a INNER JOIN b
ON a.id = b.id
AND StrComp(a.id, b.id, 0) = 0
It is a fact that Jet will optimize a JOIN on an index exactly the same way it would optimize the equivalent WHERE clause (i.e., implicit JOIN). Stripped down to just the JOIN (presumably on indexed fields), these two SQL statements will be optimized identically by Jet:
SELECT *
FROM a INNER JOIN a
ON a.id = b.id
SELECT *
FROM a, b
WHERE a.id = b.id
My question is whether or not these three will optimize identically:
SELECT *
FROM a INNER JOIN b
ON a.id = b.id
AND StrComp(a.id, b.id, 0) = 0
SELECT *
FROM a INNER JOIN b
ON a.id = b.id
WHERE StrComp(a.id, b.id, 0) = 0
SELECT *
FROM a, b
WHERE a.id = b.id
AND StrComp(a.id, b.id, 0) = 0
I'm using SO to avoid work I'm supposed to do for tomorrow, so don't have time to create a sample database and set up SHOWPLAN to test this, but the OP should definitely give it a try and report back on the results (assuming he/she is definitely intending to do this with Jet).
Have you tried StrComp? Not an Access-bod, but I think the query would look something like this:
SELECT * FROM MyTable A INNER JOIN MyTable B
on StrComp(A.description,B.description, 0) = 0
The 0 argument in StrComp causes a binary compare which will catch differences between "You" and "you" (for example).
I believe that SQL in Access is not case sensitive. Try this Kb article for a possible solution.
Here's another possible solution. As mentioned in the posting, you are sacrificing speed...
Here's a variation of the earlier suggestion to use StrComp, but this one will start by narrowing down the join using indexes, then restrict it further using StrComp.
SELECT * FROM MyTable A INNER JOIN MyTable B
on A.description = B.description
AND StrComp(A.description,B.description, 0) = 0
This should be fast even on large data sets, as long as you don't have lots of entries that are distinguished only by case.