Mysql Query to check 3 tables for an existing row - php

What I want to do is to query three separate tables into one row which is identified by a unique reference. I don't really have full understanding of the Join clause as it seems to require some sort of related data from each table.
I know I can go about this the long way round, but can not afford to lose even a little efficiency. Any help would be greatly appreciated.
Table Structure
package_id int(8),
client_id int(8),
unique reference varchar (40)
Each of the tables have essentially the same structure. I just need to know how to query all three, for 1 row.

If you have few tables that are sharing the same or similar definition, you can use union or union all to treat them as one. This query will return rows from each table having requested reference. I've included OriginTable info in case your code will need to refer to original table for update or something else.
select 'TableA' OriginTable,
package_id,
client_id
from TableA
where reference = ?
union all
select 'TableB' OriginTable,
package_id,
client_id
from TableB
where reference = ?
union all
select 'TableC' OriginTable,
package_id,
client_id
from TableC
where reference = ?
You might extend select list with other columns, provided that they have the same data type, or are implicitly convertible to data type from first select.

Let's say you have 3 tables :
table1, table2 and table3 with structure
package_id int(8),
client_id int(8),
unique reference varchar (40)
Let's assume that column reference is unique key.
Then you can use this:
SELECT t1.exists_row ,t2.exists_row ,t3.exists_row FROM
(
(SELECT COUNT(1) as exists_row FROM table1 t1 WHERE
t1.reference = #reference ) t1,
(SELECT COUNT(1) as exists_row FROM table1 t2 WHERE
t2.reference = #reference ) t2,
(SELECT COUNT(1) as exists_row FROM table1 t3 WHERE
t3.reference = #reference ) t3
) a
;
Replace #reference with actual value of unique key
or when you provide output of
SHOW CREATE TABLE
I can rewrite SQL with actual query

It is entirely possible to create a join between tables using a where clause. In fact this is often what I do as I find it leads to clearer information of what you are actually doing, and if you don't get the results you expect you can debug it bit by bit.
That said however a join is certainly a lot quicker to write!
Please bear in mind I'm a bi rusty on SQL so I may have missed remembered, and I'm not going to include any code as you haven't said what DBMS you are using as they all have slightly different code.
The thing to remember is that the join functions on a column with the same data (and type) within it.
It is much easier if each table has the 'joining' field named the same, then it should be a matter of
join on <nameOfField>
However if you wish to use field that have different names in the different tables you will need to list the fully qualified names. ie tableName.FieldName
If you are having trouble with natural, inner and outer, left and right, you need to think of a venn diagram with the natural being the point of commonality between the tables. If you are using only 2 tables inner and outer are equivalent to left and right (with each table being a single circle in the venn diagram) and left and right being the order of the tables in your list in the main part of your select (the first being the left and the second being the right).
When you add a third table this is where you can select any of the cross over section using these keywords.
Again however I have always found it easier to do a primary select and create a temp table, then perform my next join using this temp table (so effectively only need to use natural or left and right again). Again I find this easier to debug.
The best thing is to experiment and see what you get in return. Without a diagram of your tables this is the best I can offer.
in brief...
nested selects where field = (select from table where field = )
and temp tables
are (I think) easier to debug... but do take more writting !
David.

array_of_tables[]; // contain name of each table
foreach(array_of_tables as $val)
{
$query="select * from `$val` where $condition "; // $conditon
$result=mysqli_query($connection,$query);
$result_row[]=mysqli_fetch_assoc($result); // if only one row going to return form each table
//check resulting array ,for your row
}

SELECT * FROM table1 t1 JOIN table2 t2 ON (t2.unique = t1.unique) JOIN table3 t3 ON (t3.unique = t1.unique) WHERE t1.unique = '?';
You could use a JOIN like this, assuming all three tables have the same unique column.

Related

How to get value from one table column when two columns of the same name exist in an sql join

I am currently faced with the problem of trying to get a value when I have joined two tables with columns of the same name eg: table1.date and table2.date (date is different in each table) how would I get the "date" of table 1 in this instance.
I am currently running
while($row = $mysqliquery->fetch_object()) {
is there any way that I could use some form of syntax to retrieve the date from table 1 within the following code
$row->date eg $row->table1.date or something
If not how else would I be able to accomplish this?
Thanks.
You should differentiate between 2 columns with the same name by using an alias for one or both of the 2 columns in the query like this
SELECT a.`date`, b.`date` as b_date
FROM table1 a
JOIN table2 b ON a.id = b.a_id
WHERE some specific criteria
Now when your retrieve the ROW each date has its own unique name i.e.
$row->date;
$row->b_date;
I was thinking more along the lines of this ( ficticious ) pseudo sql
select a.`account_id`, a.`date` as 'account_date', u.`date` as 'signup_date'
from `accounts` a
left outer join `users` u on u.`uid`=a.`uid`
Each table has a column called date but in the sql they are each referenced with a unique alias. You cannot have two columns in the same query with the same name or you'll get errors, so you give them an alias. The tables are also aliased in this code - it really helps simplify things in my opinion... Anyway, just a quick example to illustrate how you might approach this - others may have a different approach from which I might learn new tricks

How to join two large tables with different strings

I have two tables
table1
customer_id
101
102
103
and table2
customer_id country_id
AO-101 1
AO-102 2
AO-103 3
both the tables are very large tables I have used CONCAT(table1.customer_id) for joining with the table2
all the fields stated above are index fields
joining them and getting all the customer of country 1 is taking lot of time
Can anyone help me please?
You can try this mate:
SELECT * FROM table1
JOIN table2 ON CONCAT('AO-', table1.customer_id) = table2.customer_id
WHERE table2.country_id = 1;
or this one:
SELECT * FROM table2
JOIN (
SELECT CONCAT('AO-', customer_id) AS in_customer_id, table1.* FROM table1
) AS table1 ON table1.in_customer_id = table2.customer_id
WHERE table2.country_id = 1;
I believe the problem you are running into is HOW an index is stored.
The way to understand this is to literally think of a PHYSICAL index that sits NEXT to the table as alookup.
If you do something like "create index index_1 on table1(column_1)", what this is does is stores this right next to the table and before you run a query referencing that table, the the DBMS looks over the tables and your query and determines the best way to query the tables based on indexes, table sizes, etc.
Now, the index stores literally the exact value in the exact DATATYPE as the field, unless you cast the index as a different datatype.
Right now you are joining an integer field to a character field and right there, you are not going to get the same performance from the index as you cannot use the index purely as such - it has to be translated on the fly, so to speak.
So what I would do is type something like:
create index on table2(cast(replace(customer_id,'AO-','') as integer));
This should store an integer value as the INDEX so when joined to the integer primary key, the index should run fine.
Also, why don't you just store the same integer value instead of adding this 'AO-' thing?
mysql uses CONCAT() to concatenate strings
So we use following query:
ON tableTwo.query = concat('category_id=',tableOne.category_id)
Hope this helps to you.
You can write a subquery like this:
SELECT * FROM table1 JOIN
(SELECT SUBSTRING_INDEX(customer_id, '-', -1) AS customer_id, country_id
FROM table2) t2 USING customer_id;
I haven't tried it, but you might also be able to join directly:
ON SUBSTRING_INDEX(table2.customer_id, '-', -1) = table1.customer_id
Try This Code It's Working.
select * from table4 t4, table3 t3 where t4.cus_id in (CONCAT('A0-', t3.cus_id)) && t4.country=1 ;

MYSQL - Getting the value from a field in a lookup table and main table in the same query

I have 2 table which I will describe below:
1) The main table which has an auto increment by U_ID and has a column named RU_ID which refers to the ID of a lookup table.
2) The Lookup table is auto incremented by RU_ID and has a column named ROLE which has a sting value.
Now I am needing a SELECT statement that show me all the values of the main table (SELECT * FROM...) and the ROLE value of the lookup table.
I have this so far:
Note that the = 2 is static for this example only, this will be a variable which holds the RU_ID number. Also this example will be used in PHP - PDO, but the SQL query is generic really.
SELECT *
FROM tbl_users as u
WHERE u.RU_ID = 2
AND STATUS = 1
AND u.RU_ID IN
(SELECT ROLE
FROM tbl_role_users, tbl_users
WHERE RU_ID = 2)";
Thanks for looking into this with me.
have you tried a JOIN?
SELECT t.*, t1.role
FROM tbl_users t
JOIN tbl_role_users t1 ON t.RU_ID = t1.RU_ID -- # --or t1.ID whichever is referenced
WHERE t1.RU_ID = 2
AND t.status = 1;
if you want to join the table without filtering excess rows then just add LEFT before the JOIN
Note:
I would recommend you steer away from the pre ANSI way of joining tables and actually use the JOIN syntax as its easier to read in complicated queries and or you can have more functionality with the JOIN syntax.. and that way you dont need the IN() statement

MySQL joining tables with join

I've been scratching my head at this problem all day and I simple just can't work it out. This is the first time I've attempted to try and use SQL Joining, while we do kinda get taught the basics I'm more into pushing a little more into the advanced stuff.
Basically I'm making my own forum, and I have two tables. f_topics (The threads) and f_groups (The forums, or categories). There is a relationship between topicBase in f_topics and groupID in f_groups, this shows which group each topic belongs to. Each topic has a unique ID called topicID and same for the groups, called groupID.
Basically, I'm trying to get all these columns into a single SELECT statement - The title of the topic, the date the topic was posted, the ID of the group the topic belongs in, and the name of that group. This is what I was trying to use, but the group always comes back as 1, even if the topic is in groupID 2:
$query=mysqli_query($link, "
SELECT `topicName`, `topicDate`, `groupName`, `groupID`
FROM `f_topics`
NATURAL JOIN `f_groups`
WHERE `f_topics`.`topicID`='$tid';
") or die("Failed to get topic detail E: ".mysqli_error());
var_dump(mysqli_fetch_assoc($query));
Sorry if this doesn't make much sense, and if my entire logic is completely wrong, if so could you suggest an alternate method?
Thanks for reading!
To join tables, you need to map the foreign keys. Assuming your groups table has an groupID field, this is how you'd join them:
SELECT `topicName`, `topicDate`, `groupName`, `groupID`
FROM `f_topics`
LEFT JOIN `f_groups`
ON `f_topics`.`groupID` = `f_groups`.`groupID`
WHERE`f_topics`.`topicID`='$tid';
So from what I gather there is a column in f_topics named "topicBase" which references the groupID column from the f_groups table.
Based on that assumption, you can perform either an INNER JOIN or a LEFT JOIN. INNER requires there be an entry in both tables while LEFT requires there only be data in f_topics.
SELECT
f_topics.topicName,
f_topics.topicDate
f_groups.groupName
f_groups.groupID
FROM
f_topics
INNER JOIN
f_groups
ON
f_topics.topicBase = f_groups.groupID
WHERE
f_topics.topicID = '$tid'
I recommend you avoid NATURAL JOIN.
Primarily because a working query can be broken by the addition of a new column in a referenced table, which matches a column name in the other referenced table.
Secondly, for any reader (reviewer) of the SQL, which columns are being matched to which columns is not clear, without a careful review of both tables. (And, if someone has added a column that has broken the query, it makes it even more difficult to figure out what the JOIN criteria used to be, before the column was added.
Instead, I recommend you specify the column names in a predicate in the ON clause.
It's also good practice to qualify all column references by table name, or preferably, a shorter table alias.
For simpler statements, I agree that this may look like unnecessary overhead. But once statements become more complicated, this pattern VASTLY improves the readability of the statement.
Absent the definitions of the two tables, I'm going to have to make assumptions, and I "guess" that there is a groupID column in both of those tables, and that is the only column that is named the same. But you specify that its the topicBase column in f_topics that matches groupID in f_groups. (And the NATURAL JOIN won't get you that.)
I think the resultset you want will be returned by this query:
SELECT t.`topicName`
, t.`topicDate`
, g.`groupName`
, g.`groupID`
FROM `f_topics` t
JOIN `f_groups` g
ON g.`groupID` = t.`topicBase`
WHERE t.`topicID`='$tid';
If its possible for the topicBase column to be NULL or to contain a value that does not match a f_groups.GroupID value, and you want that topic returned, with the columns from f_group returned as NULL (when there is no match), you can get that with an outer join.
To get that behavior, in the query above, add the LEFT keyword immediately before the JOIN keyword.

What type of mysql query do you run to compare two fields in separate tables?

I have a mysql table(table1) which has the following row:
topic_id: 1
topics: programming
description: A programming language is an artificial language designed to...
I have another table(table2) with this row:
desc_id: 1
description: In mathematics and computer science, an algorithm is an effective...
topics: mathematics, computer science, programming
What I'm looking to do is to run a query to compare the two topics fields and let me know which topics exist in table2 that don't exist in table1.
For instance, comparing the two above I'd like to run a query to let me know that topics mathematics and computer science don't exist in table1.
I would use a subquery, but it can also be done with innerjoins :
SELECT *
FROM `table2`
WHERE `topics` NOT IN (
SELECT DISTINCT(topics)
FROM `table1`
)
you can try NOT IN
i.e.
SELECT topics FROM table2 where topics NOT IN( select topics from table1)
If you normalized your table2 so that the topics list is in a separate sub-table, this would be a trivial query. As it stands now, it's difficult as by default mysql won't see those seperate topics in table2.topics as discrete topics. It's just a long string that happens to have commas in there.
Thankfully, MySQL has the find_in_set() function, which can help out immensely, but this function isn't available elsewhere. Not having access to your dataset, I'm just guessing here, but this should do the trick:
SELECT table1.topics, count(table1.topic_id) AS cnt
FROM table1
LEFT JOIN table2.topics ON FIND_IN_SET(table1.topics, table2.topics) = 0
GROUP BY table1.topics
HAVING cnt = 0
Basically, join the tables wherever the table1 topic is NOT in a table2 topic and count how many times the table1 topic shows up like this. If it shows up zero times, then it's present in at least one record in table2.
normalize by creating a third table, one that links table 2 to table 1 with a many to many relationship.
Table_1
id, etc
Table_2
id, etc
Table_3
id, table1_id, table2_id
you could then use simple joins to create a query that will pull the relavent data
SELECT * FROM Table_1 LEFT JOIN Table_3 ON Table_1.id = Table_3.table1_id WHERE Table_3.table2_id = $table2_id
This will pull all topics for the course.

Categories