how to write the sql command in mysql - mysql

for example: the table named products there is a product name field in the table. i want to show some related items which matched by the knowed products's product name.
how to write the sql query command?
eg: if the knowed products's product name is
True Blood Season 1 DVD
i want to get all the product name which begins as True Blood Season..
if the knowed products's product name is
24 Hours Season 7 DVD
i want to get all the product name which begins as 24 Hours Season..
the sql: what's error with the sql
$query ="select p.products_id, pd.products_name, p.products_price
from " . TABLE_PRODUCTS . " p " .
TABLE_PRODUCTS_DESCRIPTION . " pd
where p.products_status = 1
and p.products_id = pd.products_id
and pd.language_id = '" . (int)$_SESSION['languages_id'] . "'
and p.products_id <> :product_id AND MATCH('products_name') AGAINST (:products_name IN NATURAL LANGUAGE MODE);

I'd look at using MySQL Full-Text search.
This should be able to take the title of your chosen product and use it to retrieve relevant matches, eg
SELECT * FROM `products`
WHERE `id` <> :product_id -- don't return current product
AND MATCH(`product_name`)
AGAINST (:product_name IN NATURAL LANGUAGE MODE)
This requires you to create a full-text index on your products.product_name column.

select * from products where name like 'True Blood Season%'
select * from products where name like '24 Hours Season%'

SELECT * FROM products WHERE product_name='title of show here';
It's pretty basic SQL, I'd really recommend reading up a bit before posting as this question is very entry level. I'm more than happy to help you get started though :).

Related

Joins in mysql what to do

Well I wrote a query and get an error:
Column 'product_id' in field list is ambiguous
Error No: 1052
I need to select the same id from 2 tables and compare them by price here is query I wrote:
$product_sql_test1 = $this->db->query("SELECT `product_id` and 'price' FROM `" . DB_PREFIX . "product_to_category`INNER JOIN (oc_product)ON oc_product.product_id=prdoduct_to_category.product_id WHERE product_to_category.id=product.id and price >150 and `category_id`='".$product_info['related_kv4nt_id_1']."' GROUP BY `product_id` ORDER BY rand() LIMIT 0,10");
Where could be an error and how to fix it? Sorry if the question is too simple.
You have to mention the table name while selecting the product_id because many tables have this column and mysql is confused to select the column from which table
$product_sql_test1 = $this->db->query("SELECT oc_product.`product_id` and 'price'
FROM `" . DB_PREFIX . "product_to_category`INNER JOIN (oc_product)ON
oc_product.product_id=prdoduct_to_category.product_id WHERE product_to_category.id=product.id and price >150 and prdoduct_to_category.`category_id`='".$product_info['related_kv4nt_id_1']."'
GROUP BY oc_product.`product_id` ORDER BY rand() LIMIT 0,10");
Use the full name:
Tablename.ColumnName
For Example in the GROUP BY part it is not clear which product_id you mean.
Both in your Select and your Group By, you need to use your alias table names along with your column names because the same column is present in multiple tables and thus there's a confusion as to which one to use for the result.
Use an Alias name for tables and columns.
Access it like oc.product_id (for column) and oc_product oc(for table)
The correct way to do this is
$product_sql_test1 = $this->db->query("SELECT `p`.`product_id`, `p`.`price` FROM `" . DB_PREFIX . "product_to_category` `p2c` LEFT JOIN `" . DB_PREFIX . "product` `p` ON `p`.`product_id` = `p2c`.`product_id` WHERE `p`.`price` > 150 and `p2c`.`category_id`='" . (int) $product_info['related_kv4nt_id_1'] . "' GROUP BY `p`.`product_id` ORDER BY rand() LIMIT 0,10");
You should also consider formatting your SQL to make it easier to read as well

Mysql total amount (price) in cart from many tables

I met what I believe is a very common problem with mysql and e-commerce shop ... though I can't find answer for this.
I've got shop which has not one product table but many ... for example in one shop has vinyls, studio gear etc ... so we've got many tables with different product details ... the thing is I need to get total amount (price) of products in cart from many tables
public static function GetTotalAmount() {
$params = array(
':cart_id' => self::GetCartId()
);
$sql = 'SELECT SUM(v.price) AS total_amount '.
'FROM shopping_cart sc '.
'INNER JOIN vinyl v '.
'ON sc.product_id = v.id AND sc.department_id = 1 '.
'WHERE sc.cart_id = :cart_id AND sc.buy_now;';
$v = DataBase::FetchOne($sql, $params);
$sql = 'SELECT SUM(sg.price) AS total_amount '.
'FROM shopping_cart sc '.
'INNER JOIN studio_gear sg '.
'ON sc.product_id = sg.id AND sc.department_id = 2 '.
'WHERE sc.cart_id = :cart_id AND sc.buy_now;';
$sg = DataBase::FetchOne($sql, $params);
return $sg + $v;
}
As you might see I made this with ugly way .. maybe you can help me show how to get SUM() of possible N tables counted from N.price.
You can use UNION ALL
SELECT SUM(price) FROM ((SELECT SUM(price) as price FROM table1 WHERE ...) UNION ALL (SELECT SUM(price) as price FROM table2 WHERE ...) UNION ALL ....)
A quick tip (if you can) - merge all the products tables into one table and operate on that (you'll also have to implement categories and custom attributes for products though). Otherwise you will have a mess when you add new shops.
You can create a (materialized) view with just the necessary columns of the product tables, - product_id and price
Once you have the view (vw_products) you can just do an inner join of shopping cart table with the view and then get the sum.
SELECT sum(vw.price) FROM
shopping_cart sc INNER JOIN vw_products vw
ON sc.product_id = vw.id and sc.department_id IN (1,2,...)
WHERE sc.cart_id = :cart_id AND sc.buy_now;
If you have many rows and if the prices don't change often (every few minutes)
I would suggest creating a table and populating it with the result of above query.
Every day or after every change to price you can refresh this table.

Subquery without where-clause

Here's my code
SELECT res.type,
res.contactname,
res.id,
res.inv_addressline2,
res.inv_addressline3,
res.signup_date,
res.engineer_id_global,
res.job_id_global,
res.neg_or_pos,
res.rating,
res.author_id_global,
res.timestamp_global,
res.short_description,
res.job_title,
res.feedback,
author_data.contactname AS `author_name`,
review_count.total_feedback,
review_count.total_rating
FROM (SELECT mb.type,
mb.contactname,
mb.id,
mb.inv_addressline2,
mb.inv_addressline3,
mb.signup_date,
fb.engineer_id AS `engineer_id_global`,
fb.timestamp AS `timestamp_global`,
fb.job_id AS `job_id_global`,
fb.neg_or_pos,
fb.rating,
fb.feedback,
fb.author_id AS `author_id_global`,
ac.engineer_id,
ac.timestamp,
ac.author_id,
jb.job_id,
SUBSTR(jb.job_description, 1, 200) AS `short_description`,
jb.job_title
FROM " . MEMBERS_TABLE . " AS mb
LEFT JOIN " . ACCEPTED . " AS ac
ON mb.id = ac.engineer_id
LEFT JOIN " . FEEDBACK . " AS fb
ON ac.job_id = fb.job_id
LEFT JOIN " . JOBS . " AS jb
ON fb.job_id = jb.job_id
WHERE mb.type = 2
ORDER BY
fb.timestamp DESC
) AS res
LEFT JOIN
(SELECT mb.id,
mb.contactname,
fb.author_id
FROM " . MEMBERS_TABLE . " AS mb
LEFT JOIN " . FEEDBACK . " AS fb
ON fb.author_id = mb.id
LIMIT 1
) AS `author_data`
ON res.author_id_global = author_data.author_id
LEFT JOIN
(SELECT COUNT(fb.engineer_id) AS `total_feedback`,
SUM(fb.rating) AS `total_rating`,
fb.engineer_id
FROM " . FEEDBACK . " AS fb
) AS `review_count`
ON res.engineer_id_global = review_count.engineer_id
GROUP BY res.contactname
ORDER BY res.contactname
I'm just starting to get my head around SQL. My worry is the second and third inner query. Am I right in saying it will return all results as there is no where clause and the return the results from that using the "ON" statement or is the "ON" statement combined with the initial query?
There are a number of issues with this script:
You have a number of tables with names like " . MEMBERS_TABLE . ", " . ACCEPTED . " and so on. These are unlikely to be acceptable in MySQL, which normally uses backticks (`) to quote object names; if this script is to be preprocessed by eg. Perl or Python, or is part of a larger script in another language, it would be helpful to say so.
You have an order by clause, for no apparent reason, in your first sub-query. This could be removed.
Your second sub-query links FEEDBACK to MEMBERS_TABLE and limits the results to 1, without specifying the author_id inside the sub-query - this means that a single, random member will be selected inside the sub-query, then linked to the rest of the dataset on the specific author ID, which won't match for most of the rest of the dataset.
The FEEDBACK table is completely irrelevant here, and can be removed.
If id uniquely identifies a record on MEMBERS_TABLE, the sub-query can be completely removed and replaced with a single left join to MEMBERS_TABLE on res.author_id_global = MEMBERS_TABLE.id. No limit clause would be required.
If id does not uniquely identify a record on MEMBERS_TABLE, the sub-query should be rewritten as select distinct id, contact_name FROM " . MEMBERS_TABLE . " AS mb where res.author_id_global = mb.id LIMIT 1. If there are multiple matching authors for the same id, one would be selected at random.
The third sub-query does not require a where clause - it will summarise all engineers' feedback and ratings by engineer within the sub-query, and each engineer will then be linked to the corresponding engineer from the rest of the dataset by the on condition from the left join clause.
Second inner query is having limit 1. It is nothing but where condition to show only one result. Third inner query is not having any problem.

Translate MySQL query - am I interpreting this correctly?

I am just trying to translate a section of a query:
...OR... AND Zip.id IN (SELECT plan_id FROM plans_zips
WHERE zip_id = (SELECT id FROM zips WHERE title = '" . $Zip . "'))
From what I can tell the query is saying this:
Get all Zip.ids (from zips table) and get plan_id (from plan_zips table)
WHERE zip_id (using plans_zips) = zip.id where the full zip (title) matches the var $Zip.
what you're suggesting is right.
For MySQL it's much more optimal to use joins in place of nested sub-queries like this. The optimizer will be unable to optimize sub-queries and they must be run with the deepest one first.
Not quite.
If you indent the SQL a bit, it will become clearer.
...OR... AND
Zip.id IN
(SELECT plan_id FROM plans_zips WHERE zip_id = //Get all the plan_ids where
(SELECT id FROM zips WHERE title = '" . $Zip . "'))//the zip_id is the value returned from this query.
I agree with James C though - joins are much better and easier to read

How to join 1 table twice in the same query and keep results separate

we're building a scheduler system and have a couple of situations where we're trying to get some notes from a table to display. We've looked at other answers and none seem to quite match this problem.
The bookings table holds a numeric reference to both a client note (if present) and a stylist note (if present).
The notes table holds both client and stylist notes, each indexed by a unique numeric index
We've got our query working when we just want to read in the client notes:
SELECT bookings.bookingID, UNIX_TIMESTAMP(bookings.startDate) AS start_date, UNIX_TIMESTAMP(bookings.endDate) as end_date, clientDetails.firstName, clientDetails.lastName, clientDetails.phone1, clientDetails.phone2, clientDetails.email, services.name, services.serviceID, cNotes.note as client_notes, sNotes.note as stylist_note
FROM bookings
LEFT JOIN clientDetails ON bookings.clientID = clientDetails.clientID
LEFT JOIN services ON bookings.serviceID = services.serviceID
LEFT JOIN notes ON bookings.clientNotes = notes.notesID
WHERE bookings.startDate >= '" . $start_date . "' AND bookings.endDate <= '" . $end_date . "' AND bookings.stylistID = '" . $stylist_id . "'
ORDER BY bookings.startDate ASC;
Using this logic we can access the cient notes from the results array in php simply as: $results_array['note']
What we also want to be able to do is to get the stylist note for that booking as well, something like $results_array['stylist_note'].
How can we join the notes table again this time using:
LEFT JOIN notes ON bookings.stylistNotes = notes.notesID
BUT be able to reference these stylist notes separately from the client notes.
Thanks so much for any assistance.
You should be able to alias the table and columns:
SELECT ..., stylistnotes.note AS stylist_note
FROM ...
LEFT JOIN notes stylistnotes ON bookings.stylistNotes = stylistnotes.notesID