My website may have individual price list for user. When I left join imported product table on all products table I don't know where to put WHERE which would only do left join on specific rows at right table (logged user rows).
I need to do this in opencart, but it doesnt matter, it's just SQL
$sql = "SELECT * FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON
(p.product_id = pd.product_id) LEFT JOIN " . DB_PREFIX . "import i ON (p.ean = i.ean_code) WHERE
i.import_id = '" . (int)$query->row['import_id'] . "'";
I somehow need to do WHERE on import table first, but in example above it does it afterwards. Do I have to execute 2 queries?
Use parameters where you can. You need to move the condition to the on clause:
SELECT *
FROM " . DB_PREFIX . "product p LEFT JOIN
" . DB_PREFIX . "product_description pd
ON p.product_id = pd.product_id LEFT JOIN
" . DB_PREFIX . "import i
ON p.ean = i.ean_code AND
i.import_id = ?
You should also be selecting the explicit column names. This is particularly important in a LEFT JOIN, because the tables share column names (at least product_id) and you don't know which is referenced by "product_id" in the application code.
Related
i have an sql statement that retrives information from multiple tables but some of them have same columns name.
For exemple the products table has the image column which can also be found in the manufacturer table.
I don't want to overwrite the product image with the manufacturer image. I only need to get the name column from the manufacturer table AS "manufacturer" . The rest needs to r
This is my code:
$sql = "SELECT * FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "manufacturer m ON (p.manufacturer_id = m.manufacturer_id) LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id) WHERE pd.language_id = '" . (int)$this->config->get('config_language_id') . "'";
Thank you!
I need a query to get all products from opencart mysql. I am using this query.
"SELECT * FROM `" . DB_PREFIX . "product`";
but I can't get product name or title in this query. Actually I am creating another application and I want to export all products into new DB.
Real sql
SELECT * FROM oc_product p LEFT JOIN oc_product_description pd ON (p.product_id = pd.product_id) WHERE pd.language_id = '1' GROUP BY p.product_id ORDER BY pd.name ASC
First take oc_ into consideration as this is DB_PREFIX.
Then take pd.language_id='1' into consideration as it retrieves products only having language_id=1. If there are multiple language then you have to find the language_id and change it.
This is to retrieve all
SELECT * FROM " . DB_PREFIX . "product p LEFT JOIN " . DB_PREFIX . "product_description pd ON (p.product_id = pd.product_id)
I have a PHP script that retrieves messages from a database and then displays them in an inbox style way, one line for each message. Each message is part of a conversation between 2 users. Right now, the problem is that it returns 1 new message in the output for every message in the conversation.
If that makes sense? Here is the code for the query:
$sql_select_messages = $db->query( ... );
Where the argument is the following query string:
SELECT m.admin_message, a.name, u.username AS sender_username,
m.* FROM " . DB_PREFIX . "messaging m
LEFT JOIN " . DB_PREFIX . "items a ON a.items_id=m.items_id
LEFT JOIN " . DB_PREFIX . "users u ON u.user_id=m.sender_id
WHERE m.receiver_id='" . $session->value('user_id') . "' AND m.receiver_deleted=0" .
(($page == 'summary') ? " AND m.is_read=0" : '') . "
ORDER BY " . $order_field . " " . $order_type . " LIMIT " . $start . ", " . $limit
The part of:
m.* FROM " . DB_PREFIX . "messaging m
selects the data from mySQL rows that contains columns like
topic_id
and
message_id
What I'm trying to do is have the above mySQL query returns only return ONE (1) result per topic_id (as there may be several topic_id with the same number) and combined with that only the LATEST (highest number) of the message_id.
So basically if there is:
================
topic_id | message_id
================
15 10
15 11
15 12
19 02
19 03
19 04
I would only want mySQL to return 15/12 and 19/04. How would I go about doing that with the above mySQL select query?
Thank you very much :)
You need to order by two columns, and also group those columns.
Append following scripts to your SQL.
GROUP BY topic_id
ORDER BY topic_id DESC, message_id DESC
Hope this helps.
Simply:
SELECT topic_id, MAX(message_id)
FROM test
GROUP BY topic_id
http://sqlfiddle.com/#!2/271de/2/0
Your query might look like this
SELECT m.admin_message, a.name, u.username sender_username, m.*
FROM
(
SELECT MAX(message_id) message_id
FROM messaging
WHERE ... -- < all your where conditions go here
GROUP BY topic_id
) q JOIN messaging m ON q.message_id = m.message_id LEFT JOIN items a
ON a.items_id = m.items_id LEFT JOIN users u
ON u.user_id = m.sender_id
ORDER BY ...
LIMIT ...
Here is SQLFiddle demo
Now on php side it will look like
$sql = "SELECT m.admin_message, a.name, u.username sender_username, m.*
FROM
(
SELECT MAX(message_id)
FROM " . DB_PREFIX . "messaging
WHERE m.receiver_id = '" . $session->value('user_id') . "' AND m.receiver_deleted = 0 " .
(($page == 'summary') ? " AND m.is_read = 0" : '') . "
GROUP BY topic_id
) q JOIN " . DB_PREFIX . "messaging m ON q.message_id = m.message_id LEFT JOIN " . DB_PREFIX . "items a
ON a.items_id = m.items_id LEFT JOIN " . DB_PREFIX . "users u
ON u.user_id = m.sender_id
ORDER BY " . $order_field . " " . $order_type . " LIMIT " . $start . ", " . $limit;
$sql_select_messages = $db->query($sql);
I have 3 tables, want to write the select result but I don't know how to use 'join' 'inner' 'outer', etc, would be grateful if someone help me.
Tables: manufacturers / products / products_description
$manufacturer_query = "SELECT manufacturers_id from manufacturers WHERE manufacturers_name='" . $m ."'";
$manufacturer = mysql_query($manufacturer_query);
$mresult = mysql_fetch_array($manufacturer);
$products_query = "SELECT p.products_id, pd.products_description FROM products p, products_description pd WHERE p.products_id=pd.products_id AND p.manufacturers_id=" . $mresult['manufacturers_id'];
$products = mysql_query($products_query);
$presult = mysql_fetch_array($products);
$c = 0;
while ($presult){
$c++;
echo $c . ' - ' . $prod['p.products_id'] . ' - '.$prod['pd.products_description'].' - ' . $mresult['manufacturers_id'] . '<br>';
}
For your second query ($products_query), you already have a join.
The comma between the two table names (products and products_description) is a join operator.
This could be rewritten, replacing the comma join operator with the the JOIN keyword, and relocating the join predicate into an ON clause e.g.
SELECT p.products_id
, pd.products_description
FROM products p
JOIN products_description pd
ON pd.products_id=p.products_id
AND p.manufacturers_id = 1
This is an "inner" join in that rows for p.manufacturers_id = 1 will be returned ONLY if (at least one) row exists in the products table that matches that, AND if there is also at least one row in the products_description table that has a value in products_id that matches a row (or rows) returned from the products table.
Adding the keyword INNER before the JOIN keyword does not change the statement, it has no effect.
Given these table contents:
TABLE: products
manufacturers_id products_id
1 222
1 333
1 444
TABLE: products_description
products_id products_description
222 foo
444 fee
444 fi
444 fo
444 fum
That query would return:
p.products_id pd.products_description
222 foo
444 fee
444 fi
444 fo
444 fum
If you add the LEFT keyword before the JOIN keyword, then the query would be an OUTER join, and the query would also return a row like:
p.products_id pd.products_description
333 (NULL)
where a row from the table on the left side of the JOIN has no matching row found in the table on the right side.
If you want the rows returned in a particular sequence, then include an ORDER BY clause at the end of your query, e.g:
ORDER BY p.products_id, pd.product_description
Absent that, MySQL is free to return the rows in an arbitrary order.
The keywords INNER and OUTER are entirely optional. They have no effect on how the statement is processed, and this is why most SQL developers omit these keywords.
A LEFT JOIN is an OUTER join. Rows will be returned from the table on the left even when no matching row is found in the table on the right.
(For a cross join, we do usually include the CROSS keyword, even though it has no effect, just because it serves as documentation that the omission of an ON clause is intentional.)
The call to mysql_fetch_array should be in the loop:
$products = mysql_query($products_query);
$c = 0;
while ($prod = mysql_fetch_array($products) ) {
$c++;
echo $c . ' - ' . $prod['products_id'] . ' - '.$prod['products_description'].' - ' . $mresult['manufacturers_id'] . '<br>';
}
The mysql_ interface is DEPRECATED. New development should use either the mysqli_ or PDO interface.
try this with INNER JOIN
$manufacturer_query = "SELECT m.manufacturers_id , p.products_id, pd.products_description FROM manufacturers m
INNER JOIN products p ON p.manufacturers_id= m.manufacturers_id
INNER JOIN products_description pd ON p.products_id=pd.products_id
WHERE manufacturers_name='" . $m ."'";
$products = mysql_query($manufacturer_query);
$presult = mysql_fetch_array($products);
$c = 0;
while ($presult){
$c++;
echo $c . ' - ' . $prod['p.products_id'] . ' - '.$prod['pd.products_description'].' - ' . $mresult['manufacturers_id'] . '<br>';
}
EDIT
$manufacturer_query = "SELECT m.manufacturers_id mm, p.products_id pp, pd.products_description ppd FROM manufacturers m INNER JOIN
products p ON p.manufacturers_id= m.manufacturers_id INNER JOIN
products_description pd ON p.products_id=pd.products_id WHERE manufacturers_name='" . $m ."'";
$products = mysql_query($manufacturer_query);
$c = 0;
while ($presult = mysql_fetch_array($products)){
$c++;
echo $c . ' - ' . $presult['pp'] . ' - '.$presult['ppd'].' - ' . $presult['mm'] . '<br>';
}
I have a list of venues in the Venues table, and a list of a cities/states in the Locations table. The venue is associated with an area code unique to my organization, referred to as a SOYID. The SOYID is made up of a geographical area - each row in the Locations table has a City, State, and the corresponding SOYID. Some Venues rows have a SOYID, others do not; for those that do not, I need to find the SOYID for the city and state listed. I only want to select those Venues in a specific SOYID.
This query works, however, it takes a few seconds to load; I don't think I am writing the query correctly. Currently Venues has approx 140 rows, Locations has 40,000.
$sql = "SELECT DISTINCT a.VenueID, a.Name, a.PhotoID, a.City, a.StateAbbr
FROM Venues AS a LEFT JOIN Locations AS c ON a.City = c.city
WHERE a.SOYID = '" . mysql_real_escape_string($SOYID) . "'
OR ((c.city = a.City) AND (c.state = a.StateAbbr) AND (c.SOYID = '" . mysql_real_escape_string($SOYID) . "'))
ORDER BY a.Name ASC";
Any time you reference a column from a LEFT JOINed table (c.state and c.SOYID in your specific case) in the WHERE clause, you force that join to behave like an INNER JOIN. Instead, make those tests part of the join condition:
"SELECT DISTINCT a.VenueID, a.Name, a.PhotoID, a.City, a.StateAbbr
FROM Venues AS a
LEFT JOIN Locations AS c
ON a.City = c.city
AND a.StateAbbr = c.state
AND c.SOYID = '" . mysql_real_escape_string($SOYID) . "'
WHERE a.SOYID = '" . mysql_real_escape_string($SOYID) . "'
OR c.SOYID IS NOT NULL /* LEFT JOIN found a matching row */
ORDER BY a.Name ASC"
EDIT: Based on comments, this version should allow you do remove the DISTINCT requirement:
"SELECT a.VenueID, a.Name, a.PhotoID, a.City, a.StateAbbr
FROM Venues AS a
WHERE a.SOYID = '" . mysql_real_escape_string($SOYID) . "'
OR EXISTS(SELECT NULL
FROM Locations AS c
WHERE a.City = c.city
AND a.StateAbbr = c.state
AND c.SOYID = '" . mysql_real_escape_string($SOYID) . "')
ORDER BY a.Name ASC"