I need a bit help with a query. I want extract the content from three different table, this table have different records so the code key is different agains the other table. The table contains the credentials for the login, I need to check if the code and the email is found in almost one table, this is an example:
$Query = "SELECT * FROM login_tb1, login_tb2, login_tb3
WHERE (code = '".mysql_real_escape_string($code)."') OR
(email = '".mysql_real_escape_string($email)."') ";
Now when I execute this query I get this error:
Column 'code' in where clause is ambigous
I can't perform a JOIN 'cause the column code is different, all the records are different. All the table have the same structure anyway. How can I fix this?
Thanks.
It took me a while to understand that error message as well. Ambigous is such a fancy word. In human language, it means that MySQL is trying to tell you: "Hey man, the column exists in multiple tables in the select clause, so I don't know which table you mean!". You should be explicit about the table:
$Query = "SELECT * FROM login_tb1, login_tb2, login_tb3
WHERE (login_tb1.code = '".mysql_real_escape_string($code)."') OR
(login_tb1.email = '".mysql_real_escape_string($email)."') ";
If you don't care about which table and they have the same schema, you still need to be explicit, so your query will be a bit more advanced:
SELECT * FROM login_tb1 as l1, login_tb2 as l2, login_tb3 as l3
WHERE ( l1.code = 'code' OR l1.email = 'email' )
OR ( l2.code = 'code' OR l2.email = 'email' )
OR ( l3.code = 'code' OR l3.email = 'email' )
Side note: I don't know your exact use case, but it seems a bit like an anti-pattern that you have multiple login tables with the seemingly same schema. Unless you have a very specific reason not to, you should keep it in a single table.
Code column would be part of more than one table.
in this case prefix with anyone of the table..
e.g login_tb1.code
this would do the trick
You need to tell mysql which code column to use.
Apparently, that column appears in more than one table, so for each table you want to check the code column, write it like this:
tablename.code
This way mysql will know which column to use
I also suggest taking a look at your ta le structure, since having 3 tables with the same structure seems weird.
You can post a question a out the as well or elaborate.
There are similar columns in the tables. You need to properly alias the table
$Query = "SELECT t1.col,t2.col,t3.col FROM login_tb1 as t1,
login_tb2 as t2, login_tb3 as t3
WHERE (t1.code = '".mysql_real_escape_string($code)."') OR
(t2.email = '".mysql_real_escape_string($email)."') ";
Related
I am trying to replace a column in the result of the select query as denoted in
This reference but unlike the example I have many columns in the table thus I can not specify the name of every column in the select query.
I tried some ways to attain the same but none seems effective.
select
*, (REPLACE(REPLACE(role_id,1,"admin"),2,"moderator") AS role_id
from user;
or
Select *
from user
where role_id = (select REPLACE(role_id,1,"admin") as role_id from user;
Here we assume only two possible values for the role_id however at certain instanced it might have to get data from another table ie a different table that holds different ids and values corresponding to them.
So is there a way to attain the following conditions in a single query:-
to replace values of some fields returned from select query (assuming many columns writing the names of all the columns individually is not feasible)
to get the replacement values from different tables for different columns in single table.
I need to implement the above conditions in one query but the changes shouldn't be in the database only the result of select query needs to be optimized.
Already referred to the following too but could not help.
Link 1
Link 2
Link 3
I am using phpmyadmin as engine and php as the implementation language.
If i have understood your question correctly, it's easier to use CASE/WHEN
SELECT *,
CASE WHEN role_id = 1 THEN "admin" WHEN role_id = 2 THEN "moderator" END AS role_id
FROM user;
But easier still maybe to have an array in PHP,
$roles = array("1" => "admin", "2" => "moderator", .... );
and look it up in the array. that will keep your query short and sweet. The advantage of this approach is that you don't need to change your query every time you add a new role. If you get a large number of roles (say dozens) you might actually want a separate table for that.
I got this example, but I want to know in an overall way, how to fetch 2 column with the same name in MySQL without using an alias?
Example:
$query = "SELECT app.*, categorie.* FROM app JOIN categorie ON app.id = categorie.id";
while ($row = mysql_fetch_array($query)) {
$categorie = $row[categorie.name]; //is there a way to do this?
$aplicativo = $row[app.name];
}
This example is simply solved with an alias, but is there another way, something like the example? Thank you for your time
mysql_fetch_array
Warning
This extension is deprecated as of PHP 5.5.0, and will be removed in the future. Instead, the MySQLi or PDO_MySQL extension should be used. See also MySQL: choosing an API guide and related FAQ for more information. Alternatives to this function include:
mysqli_fetch_array()
PDOStatement::fetch()
If two or more columns of the result have the same field names, the last column will take precedence. To access the other column(s) of the same name, you must use the numeric index of the column or make an alias for the column. For aliased columns, you cannot access the contents with the original column name.
Example #1 Query with aliased duplicate field names
SELECT table1.field AS foo, table2.field AS bar FROM table1, table2
So in your case the query should be, as the documentation suggests, using alias or numeric index:
SELECT app.name as "app.name",... , categorie.name as "categorie.name",... FROM app JOIN categorie ON app.id = categorie.id
Use PDO's FETCH_NUM type when fetching your rows to get a 0 indexed array that will contain both values, even if they have the same column name.
function selectStuff(\PDO $pdo)
{
$stmt = $pdo->prepare('SELECT app.name, categorie.name FROM app JOIN categorie ON app.id = categorie.id');
$stmt->execute();
foreach ($stmt->fetchAll(\PDO::FETCH_NUM) as $row) {
// $row[0] contains app.name
// $row[1] contains categorie.name
}
}
You have to leverage a 0 indexed fetching of columns to be able to do that without alias. The reason is simple: you can't logically access two different values in an array if they share the same key.
Notice that I explicitely named the columns to be selected. You should prefer that to selecting all fields, for readability reason, and also (arguably this is in most cases not noticeable) for performance reasons.
Disclaimer: mysql_fetch_array()
I understand this is not what should be recommended theese days, but I havent moved away as of yet since its still running great on any PHP 5.x server around where I'm from. Soon the time is there so I can refactor my codebase, maby even sooner for all I know. That being said...
Back to your question...
I was googling and looking for something else I see after reading, but I am beginning to understand that the entire approach of being able to read what you are asking for has no practical use in real world. That is, compared to changing your query adding some aliases like this:
$query = "SELECT app.name AS appname, categorie.name AS categoriename, app., categorie. FROM app JOIN categorie ON app.id = categorie.id";
This way your returned query returns more fields with unique names so you can access them like you ask for.
But say you were looking for a way to accomplish what you ask without changing your sql-query. You need to know the order of results, especially if there are more than one ambiguous name in the list as you will not be able to reorder the ambiguous fields, MySQL does return all your fields you see its just the way an array works you do not get the answers you want. Or, my disclaimer, this is one of the reasons I should move away from this MYSQL_FUNCTIONS... (I hope so because if so this is a damn great reason alone, mysql_fetch_assoc() should have an option to lay ouu an array of results as for this example would be ['id','name','id','name'])
You do not say anthing about your DB however say they both have two columns id and name for this example. Return results for each database would be id, name or in the case of your query it would be : id, name, id, name
How does this work? A resulted array from mysql_fetch_array() looks like this:
Say app db has values: 1, app name
Say category db has values: 2, category name
Array
(
[0] => 1
[id] => 2
[1] => 'app name'
[name] => 'category name'
[2] => 2
[3] => 'category name'
)
So if you know the order of results you can atleast access the different fields even if they have the same name. However looking at the simple example above it would be hard to say if [2] is [id] or [name] but if you know the order...
Then again, select * and someone changes the database... adds a column...
$query = "SELECT app.name as `appname`, categorie.name as `catname`,
and_maybe_other_columns_here
FROM app JOIN categorie ON app.id = categorie.id";
while ($row = mysql_fetch_array($query)) {
$categorie = $row['appname']; //is there a way to do this?
$aplicativo = $row['catname'];
}
Something I've been stumbling on for a while now. I have a table called gears which contains rows with the names: id, mid, cid and installed. I want to search this table and return in csv format a list of mids for some unique cid. For example if cid = $cid I can use:
$query = $database -> query("SELECT COUNT(mid), GROUP_CONCAT(mid) FROM gears WHERE cid=$cid", __LINE__, __FILE__);
$gears_installed = $database -> get_result($query);
$gears = $database -> get_result($query, 0, 1);
Don't worry about the function names, they do exactly as one would expect. So if there were 3 rows for that specific $cid, with mids: bank, lottery and post then $gears_installed would be equal to 3 and $gears would be equal to bank,lottery,post. This works as intended.
Now on to the question I have. Each unique mid has its own table, named settings_mid_here. I.e, for the above three, I have the tables settings_bank, settings_lottery and finally settings_post. Each of these tables will also have a column called cid (this is how the two can be related). How do I go about running one query to return the entire row from each table where cid=$cid? I do not want to run a separate query for SELECT * FROM settings_bank WHERE cid=$cid and SELECT * FROM settings_post WHERE cid=$cid and finally SELECT * FROM settings_post WHERE cid=$cid, as this could result in around 10 extra queries on one page load (there are, at the moment, 10 different mids).
As you can see, the problem is dynamic. It must be able to adapt to a different number of mids, somehow differentiate the settings within each table (for example settings_bank may have a column with name name, and so might settings_post). Finally, it must also be able to return a default row (not null values) if there does not exist a row corresponding to the given $cid.
A complicated task but I hope someone can help me with this as I have not been able to get anywhere.
$queries = array();
foreach(explode(',', $gears) as $gear) {
$queries[] = "SELECT '$gear' AS gearname, settings_$gear.* FROM settings_$gear WHERE cid=$cid";
}
$sql = implode(' UNION ', $queries);
$query2 = $database->query($sql);
This query will return one row for each table, with an extra gearname column to indicate which table that row came from.
Or you can create a JOIN dynamically:
$gears_array = explode(',', $gears);
$joins = implode(' JOIN ', $gears_array);
$wheres = implode(' AND ',
array_map(function($g) use ($cid) {
return "$g.cid = $cid";
}, $gears_array));
$sql = "SELECT * FROM $joins WHERE $wheres";
$query2 = $database->query($sql);
This is not really an answer to your specific question, simply because there's no way to accomplish what you are trying with one query.
The reason is simple: RDBMSs are not designed to work this way. Tables are supposed to store data that represent entities and relations. In your case, for each distinct value of mid, a table named settings_{mid} must exist, thus forcing the mid column implicitly store (a part of) a table name. But that's not data, that's metadata.
That would not really be a problem if SQL syntax could accept variable, parametrized, column-related or arbitary table names. But it doesn't. And that's by design. Instead, an RDBMS provides you with all the tools you could ever need to relate your data to each other. By using it the intended way, you'll never have to resort to such 'dynamic' tricks.
In your case, there should be one config table with a mid column to distinguish the rows that refer to the specific mid value. Then, the query would be simple:
select * from `config` where mid='$mid' and cid='$cid'
This is the relational way. Thus the R in RDBMS. There's absolutely no reason at all to mix data with metadata. If you do, you move the relation resolution problem in higher levels of the application model.
And one last thing: One might argue that the config_{mid} tables might have similar but not identical structure. There's a solution for that too: IS-A relations.
Having said that, for your specific problem, a solution along the lines of Barmar's answer would do the trick.
I am trying to select the entries that have the same text in the "email" column of my postgreSQL table. I am completly new to database and this is the first database I ever created, so sorry if it's a silly question. My database has 3 columns: key, user_mails and json_adress.
I tried
$existent= "SELECT * FROM
(SELECT public.account_recover_users.* AS keys,emails,jsons
FROM public.account_recover_users)
WHERE emails='$email'";
but I guess I am mistaking somewhere.
Please help, I am trying to learn and I got a bit stuck.
The reason you got the error ERROR: subquery in FROM must have an alias Hint: For example, FROM (SELECT ...) [AS] foo is because you have to give an alias (nickname) to any subquery you use. So, just do what the error message hint tells you to do:
"SELECT *
FROM (
SELECT public.account_recover_users.* AS keys, emails, jsons
FROM public.account_recover_users
) as subq
WHERE emails='$email'"
But you don't need a subquery at all. This could be simplified to just:
"SELECT * FROM account_recover_users WHERE user_mails='$email'"
If you want to rename (i.e. give an alias to) your columns upon selection, I wouldn't use a subquery. Try:
"SELECT key as keys, user_mails as emails, json_adress as jsons
FROM account_recover_users
WHERE emails='$email'"
I don't really recommend this, though. If you're just going to give an alias to every column, why not rename the columns in the database?
I am writing another answer, because the currently accepted answer is wrong in several respects. Neither of the two presented queries can work, even though the OP incorrectly accepted the answer.
The original query couldn't work for several reasons:
As was mentioned (and the error message clearly states): a subquery requires an alias.
As was also mentioned, a subquery is just pointless for the simple task.
This construct is nonsense: public.account_recover_users.* AS keys You can't apply an alias after expanding * to the list of columns. Postgres just ignores it. It might throw an exception in future releases.
According to your description, existing columns are named key, user_mails and json_adress (sic!). emails or jsons are just invalid references.
Your absolutely basic query should be:
"SELECT * FROM public.account_recover_users WHERE emails = '$email'"
You can rename columns in the query by appling column aliases, but your WHERE clause cannot refer to output columns (aliases), it has to refer to input columns:
"SELECT key, user_mails AS email, json_adress AS jsons
FROM public.account_recover_users
WHERE user_mails = '$email'"
Detailed explanation in this related answer:
How to re-use result for SELECT, WHERE and ORDER BY clauses?
Because you're referencing public.account_recover_users in a derived table (in brackets), you need to give the derived table an alias which can be almost anything.
$existent= "SELECT * FROM
(SELECT public.account_recover_users.* AS keys,emails,jsons
FROM public.account_recover_users) as aru
WHERE emails='$email'";
In your case though I don't think you need a derived table at all. You could just write.
$existent = "SELECT key as keys, user_mail as emails, json_address as jsons
FROM public.account_recover_users
WHERE emails='$email'";
You don't need the subquery... (Alias it if you actually need one).
Nor do you need public, since it's in your search path by default.
Nor do you need the fields here, since you're selecting them all.
SELECT * FROM account_recover_users WHERE user_mails='$email'
Oh, and don't forget to escape $email... Look into PDO::prepare().
So, basically, I have a MySQL table called 'topics' and another one called 'replies', for example. In table 'topics', there's a field called 'relforum' which relates this topic to a forum section. And in the table 'replies', there's a field called 'reltopic', which relates the reply to a topic. Both tables have an id field, auto_increment primary key.
Now, I want to select all replies from a certain forum. Since 'replies' has no 'relforum' field, my way would be:
Select all topics with 'relforum' equal to that certain forum and loop through them
While in the loop, select all replies from the topic that is being 'processed' right now
Merge all fetch_array results in one multidimensional array, then loop through them.
That's something like this:
$query = mysql_query("SELECT * FROM `topics` WHERE `relforum` = '1'");
while($array = mysql_fetch_array($query)) {
$temp = mysql_query("SELECT * FROM `replies` WHERE `reltopic` = {$array['id']}");
$results[] = mysql_fetch_array($temp);
}
Is there a way to merge all that into fewer queries? Because this process would basically run one query per topic in that forum plus one. That would be too much :P
Adding the relforum field to the replies table is a solution (I'm still designing the DB Part so it's not a problem to add it), but I would like to see if there's a solution.
I'm really not good at SQL things, I only know the basic SELECT/INSERT/UPDATE, and I usually generate the last two ones using PHPMyAdmin, so... I guess I need some help.
Thanks for reading!
You need to learn to use joins. The link below is for SQL server but the theory for mySQl is pretty much the same for basic joins. Please do not use comma-based joins as they are 18 years outdated and are a porr pracitce. Learn to use the ANSII standard joins.
http://www.tek-tips.com/faqs.cfm?fid=4785
In accessing a database, you almost never want to use any looping. Databases are designed to perform best when asked to operate on sets of data not individual rows. So you need to stop thinking about looping and start thinking about the set of the data you need.
SELECT
r.*
FROM
replies r
INNER JOIN
topics t
ON
r.reltopic = t.id
WHERE
t.relforum = 1;
You basically need a join of two tables.
SELECT * FROM `replies`, `topics` WHERE `replies`.`reltopic` = `topics`.`id` AND `topics`.`relforum` = '1';
SELECT r.* FROM replies r, topics t
WHERE t.relforum = 1 AND r.reltopic = t.id
get rid of the backquotes. they're nonstandard and clutter the code
Yes, you should use a join here. However you will need to take greater care processing your result set.
Joins are the essential query in a relational database schema. Add them to your arsenal of knowledge :)