Excuse me for what I'm sure is an elementary question for most of you, but I have an issue with table columns from separate tables having the same name as one another, and trying to select from both tables in the same query.
Okay, so this is my code:
$q_value = $mdb2->quote($_POST['query']);
$field = $_POST['field'];
$sql = "SELECT m.*, l.name FROM memberlist m, mail_lists l
WHERE m.$field=$q_value
AND l.id = m.list
ORDER BY m.id";
$l_list = $mdb2->queryAll($sql, '', 'MDB2_FETCHMODE_ASSOC');
The table memberlist has the following columns:
id, email, list, sex, name
and the table mail_lists has the following columns:
id, name
After running the query, I later loop through the results with a foreach like so:
foreach ($l_list as $l){ //blahblah }
The problem is that the column 'name' in mail_lists refers to the names of the list, while the column 'name' in memberlist refers to the name of the member.
When I later access $l->name (within the foreach), will I get m.name, or l.name? Furthermore, how do I get access to the other?
Or will I just have to do two separate queries?
Why can you not simply use:
SELECT m.*, l.name as l_name FROM ...
and then distinguish between name and l_name?
And this is a matter of style, so others may disagree but I never use * in queries, tending to prefer explicit column specifications. That's not actually a problem in your case other than if you wanted to do:
SELECT m.*, l.* FROM ...
and still distinguish between the two names. With explicit column specifications, you can add an as clause to each column to give then unique names.
Related
I am trying to do what I just said. I have two joined tables. They are joined by same id's. But There are two columns with same name and I only want to output one of the columns.
$query= "SELECT *
FROM users
INNER JOIN bookings ON users.username = bookings.personal
JOIN products ON bookings.productid = products.productid
WHERE users.id = $id
";
$selectproductname = $db->prepare($selectuseremailquery);
$selectproductname ->execute(array());
foreach($selectproductname as $index => $rs) :
it gives me something like this table:
-id -----id----products----products------
- -
-1 1 a cup coffee cup -
-2 2 a pen a purple pen -
-----------------------------------------
I want to output the coffee cup, but there are two columns with same name. How can I output?
This didn't work:
<td><div> <?php echo $rs['products.productname']; ?> </div> </td>
And I have to select all of it with *.
Using SELECT * is generally considered harmful in production software, especially in php, for the precise reason you're asking about.
In php, sometimes the result set is loaded into an associative array. That will cause data from all but one of each set of duplicate column names to disappear.
You want to use
SELECT products.id,
products.productname,
products.id AS product_id,
bookings.*,
etc., etc.
to enumerate the columns you need in your result set. (Notice that I'm guessing at your column names).
I know your question says you have to use SELECT *. I doubt that's true. If so it's a likely to be requirement imposed by somebody who doesn't know what they're talking about. (Stupid professor tricks come to mind.)
If you do have to use SELECT *, you'll need to use the result set metadata to examine each column's metadata and figure out which columns you need to extract. getColumnMeta() does that.
I'm a bit confused about DISTINCT keyword. Let's guess that this query will get all the records distincting the columns set in the query:
$query = "SELECT DISTINCT name FROM people";
Now, that query is fetching all the records distincting column "name" and at the same time only fetching "name" column. How I'm supposed to ONLY distinct one column and at the same time get all the desired columns?
This would be the scheme:
NEEDED COLUMNS
name
surname
age
DISTINCTING COLUMNS
name
What would be the correct sintaxis for that query? Thanks in advance.
If you want one row per name, then a normal method is an aggregation query:
select name, max(surname) as surname, max(age) as age
from t
group by name;
MySQL supports an extension of the group by, which allows you to write a query such as:
select t.*
from t
group by name;
I strongly recommend that you do not use this. It is non-standard and the values come from indeterminate matching rows. There is not even a guarantee that they come from the same row (although they typically do in practice).
Often, you want something like that biggest age. If so, you handle this differently:
select t.*
from t
where t.age = (select max(t2.age) from t t2 where t2.name = t.name);
Note: This doesn't use group by. And, it will return duplicates if there are multiple rows with the same age.
Another method uses variables -- another MySQL-specific feature. But, if you are still learning about select, you should probably wait to learn about variables.
I have 2 tables, a users table and a trade table.
Which look like:
The structure of my code right now is:
<?php
$history = mysqli_query($con, "SELECT * FROM .......");
while($row = mysqli_fetch_array($history)) {
echo("The sentence");
} ?>
Problem I'm facing is that I'm trying to echo the user_name which in one case has to be the receiver and other the person giving it.
Pro tip: Never use SELECT * in software unless you know exactly why you are doing so. In your case it is harmful.
I'm assuming your query is really against the user and trade tables you mentioned in your question.
First, recast your query using 21st century SQL, as follows:
SELECT *
FROM trade AS t
JOIN user AS s ON s.user_id = t.user_id_sender
WHERE s.facebook_id = $fbid
Second, use this to retrieve your user's names and the item id traded.
SELECT s.user_name AS sender,
r.user_name AS receiver,
t.trade_id AS item_id
FROM trade AS t
JOIN user AS s ON s.user_id = t.user_id_sender
JOIN user AS r ON r.user_id = t.user_id_receiver
WHERE s.facebook_id = $fbid
See how we JOIN the user table twice, with two different aliases s (for sender) and r (for receiver)? That's the trick to fetching both names from IDs.
See how we employ the aliases sender and receiver to disambiguate the two user_name columns in the result set?
Now, when you use the php fetch_array function, you'll end up with these elements in the array.
$history['sender']
$history['receiver']
$history['item_id']
The array index strings correspond to the alias names you specified in your SELECT clause in your query.
So, one reason to avoid SELECT * is that you can get more than one column with the same name, and that means fetch_array will eliminate those duplicates and so it will lose useful information from your result set.
I had my query set up the other day as so
$query = "SELECT card_id,title,description,meta_description,seo_keywords,price
FROM cards,card_cheapest order by card_id";
As you can see, I was selecting card_id,title,description,meta_description,seo_keywords from the table cards, and price was coming from cheapest_card. They both have the card_id in common (in both tables). However, I ran into a bit of an issue. When I run the query in navicat lite, I receive an error "card_id is ambiguous". Was I doing something wrong?
When 2 or more tables have a column that is named the same, you have to qualify the table you want the column to be from.
i.e.:
$query = "SELECT cards.card_id,title,description,meta_description,seo_keywords,price
FROM cards,card_cheapest order by card_id";
Furthermore, do you really want to run the query this way, without a WHERE/JOIN-clause to define how to JOIN the two tables?
$query = "SELECT cards.card_id,title,description,meta_description,seo_keywords,price
FROM cards,card_cheapest WHERE cards.card_id = card_cheapest.card_id
ORDER BY card_id";
When you have the same column name in two tables you're selecting from, you have to prefix the part in the SELECT with one of the table names (it doesn't matter which if it's the same data)
such as SELECT cards.card_id, ...
EDIT: However, cularis's answer is much more explanatory than mine, and take note about joining the two card_id columns if you want to get correct results.
When you run queries that get information from multiple tables with shared field names you need to specify from which table you want to extract what field. You do this by specifying the table name before the field name.
In your case you have two options:
cards.card_id or card_cheapest.card_id.
Also I agree with #cularis, you are probably better of doing a join, but still you will need to specify which card_id you want to select: the one from cards or card_cheapest.
With PHP I'm trying to run a SQL query and select normal columns as well as COUNT.
$sql_str = "select COUNT(DISTINCT name), id, adress from users";
$src = mysql_query($sql_str);
while( $dsatz = mysql_fetch_assoc($src) ){
echo $dsatz['name'] . "<br>";
}
The problem is that when I have "COUNT(DISTINCT name)," in my query, it will only return the first entry. When I remove it, it will return all matching entries from the db.
I could separate it and do 2 queries, but I'm trying to avoid this due to performance concerns.
What do I make wrong?
thx, Mexx
The ability to mix normal columns and aggregate functions is a (mis)feature of MySQL.
You can even read why it's so dangerous on MySQL's documentation:
https://dev.mysql.com/doc/refman/5.6/en/group-by-extensions.html
But if you really want to mix normal rows and a summary in a single query, you can always use the UNION statement:
SELECT COUNT(DISTINCT name), null, null FROM users GROUP BY name --summary row
UNION
SELECT name, id, address FROM users --normal rows
COUNT() is an aggregate function, it aggregates against the results of the rest of your query. If you want to count all distinct names, and not just the distinct names associated with the id and address that you are selecting, then yes, you will have to run two queries. That's just how SQL works.
Note that you should also have a group by clause when aggregating. I think the fact that MySQL doesn't require it is horrible, and it encourages really bad habits.
From what I understand, you want to get :
one line per user, to get each name/id/address
one line for several users at the same time, to get the number of users who have the same name.
This is not quite possible, I'd say.
A solution would be, like you said, two queries...
... Or, in your case, you could do the count on the PHP side, I suppose.
ie, not count in the query, but use an additionnal loop in your PHP code.
When you have a count() as part of the field list you should group the rest of the fields. In your case that would be
select count(distinct name), id, adress from users group by id, adress
select count(distinct name), id, adress
from users
group by id, adress
I'm assuming you want to get all your users and the total count in the same query.
Try
select name, id, address, count(id) as total_number
from users
group by name, id, address;