mysql check multiple column in on statement - mysql

I am stuck in 1 left join query in which I want to check multiple columns in on statement.
By default in the database, some column is null which I want to check in the on statement.
Now the issue is when I run a query using the OR operator it only runs the 1st condition and the rest are skipped.
If I use AND operator it throws an error.
So is there any way to get data from multiple conditions?
Here is my query:
$data = "SELECT
b.book_name, b.book_id,
b.cats_id, b.cats_id1,
b.cats_id2, b.cats_id3,
b.cats_id4, b.cats_id5,
b.cats_id6,
b.book_rating,
b.book_author,
b.book_stock,
b.book_publisher,
b.book_front_img,
b.book_status,
p.publisher_id,
p.publisher_name,
a.author_id,
a.author_name,
cat.cats_id,
cat.cats_name,
cat.cats_status
FROM
`books` AS b
LEFT JOIN `publisher` AS p
ON b.book_publisher = p.publisher_id
LEFT JOIN `author` AS a
ON b.book_author = a.author_id
LEFT JOIN categorys As cat
ON b.cats_id = cat.cats_id
OR b.cats_id1 = cat.cats_id
OR b.cats_id2 = cat.cats_id
OR b.cats_id3 = cat.cats_id
OR b.cats_id4 = cat.cats_id
OR b.cats_id5 = cat.cats_id
OR b.cats_id6 = cat.cats_id
GROUP BY
b.book_name
HAVING
cat.cats_name = '$search_data'
AND b.book_status = 1
ORDER BY
$sorting
LIMIT $offset, $page_limit"

You probably don't have more than one author displayed for your multi-author books either. You are misusing MySQL's notorious nonstandard extension to GROUP BY.
To troubleshoot this kind of query, disable that extension with SET sql_mode = CONCAT_WS(',',##sql_mode, 'ONLY_FULL_GROUP_BY'), then try your query again. You'll need more terms in your GROUP BY clause.
It looks like each books row has multiple category id columns. And it looks like you want to display information from your categorys table for each of them.
Use GROUP BY b.book_id, p.publisher_id, a.author_id, cats.cats_id to prevent MySQL's bizarro handling of GROUP BY from concealing your data.
I must add this: your multiple books.cats_id columns are not the SQLish way to handle your many-to-many relationship between books and categories. In the parlance of our trade, your books table is denormalized.
What you want is a new table called books_categorys with two columns, book_id and cats_id. It's called a join table. When a row is present in that table, it means a particular book is in a particular category. It's the SQLish way of handling a setup where each book can be in zero or more categorys. Here's an explanation. MySQL join many to many single row
Then you remove all the cats_id columns from books, and retrieve the categories like this.
Then you do something like this SELECT to get the categories.
SELECT books.id, books.name,
categorys.cats_id, categorys.cats_name, categorys.cats_status
FROM books
JOIN books_categorys ON books.book_id = books_categorys.book_id
JOIN categorys ON books_categorys.cats_id = categorys.cats_id
``

Related

MySQL DISTINCT returning not so distinct results

Good day,
I have a small issue with MySQL Distinct.
Trying the following query in my system :
SELECT DISTINCT `booking_id`, `booking_ticket`, `booking_price`, `bookingcomment_id`, `bookingcomment_message` FROM `mysystem_booking`
LEFT JOIN `mysystem_bookingcomment` ON `mysystem_booking`.`booking_id` = `mysystem_bookingcomment`.`bookingcomment_link`
WHERE `booking_id` = 29791
The point is that there are bookings like 29791 that have many comments added.
Let's say 10. Then when running the above query I see 10 results instead of one.
And that's not the way DISTINCT supposes to work.
I simply want to know if there are any comments. If the comment ID is not 0 then there is a comment. Of course I can add COUNT(blabla) as comment_number but that's a whole different story. For me now I'd like just to have this syntax right.
You may try aggregating here, to find which bookings have at least a single comment associated with them:
SELECT
b.booking_id,
b.booking_ticket,
b.booking_price
FROM mysystem_booking b
LEFT JOIN mysystem_bookingcomment bc
ON b.booking_id = bc.bookingcomment_link
WHERE
b.booking_id = 29791
GROUP BY
b.booking_id
HAVING
COUNT(bc.bookingcomment_link) > 0;
Note that depending on your MySQL server mode, you might have to also add the booking_ticket and booking_price columns to the GROUP BY clause to get the above query to run.
You can try below - using a case when expression
SELECT DISTINCT `booking_id`, `booking_ticket`, `booking_price`, `bookingcomment_id`,
case when `bookingcomment_message`<>'0' then 'No' else 'Yes' end as comments
FROM `mysystem_booking`
LEFT JOIN `mysystem_bookingcomment` ON `mysystem_booking`.`booking_id` = `mysystem_bookingcomment`.`bookingcomment_link`
WHERE `booking_id` = 29791

Syntax error in complex SQL Query condition

I am having some trouble with my sql statement.
Here is a picture of the relevant tables:
A product can be in multiple categories.
A single product can have multiple varietycategories (ie: size, color, etc)
a varietycategory can have multiple varietycategoryoptions (ie: small, medium, large)
the table searchcriteria.criterianame loosly relates to varietycategory.category
the table searchcriteriaoption.criteriaoption loosely relates to varietycategoryoption.descriptor.
I get the searchcriteria.criterianame and use that string as the value we want to match with varietycategory.category and we also have to get the various searchcriteriaoption.criteriaoption strings (for that searchcriteria.criterianame) and match that against varietycategoryoption.descriptor for that varietycategory.category.
Here is the sql:
SELECT DISTINCT categories.*, product.*
FROM (categories, product, product_category)
LEFT JOIN varietycategory ON varietycategory.productid = product.id
LEFT JOIN varietycategoryoption ON varietycategoryoption.varietycategoryid = varietycategory.id
WHERE product_category.categoryid=4
AND product.id=product_category.productid
AND categories.category_id=product_category.categoryid
AND (
(varietycategory.category = 'color' AND (varietycategoryoption.descriptor='red' OR varietycategoryoption.descriptor='blue'))
OR
(varietycategory.category = 'size' AND (varietycategoryoption.descriptor = 'small' OR varietycategoryoption.descriptor='medium'))
)
but I get an error:
Unknown column 'varietycategory.id' in 'on clause'
I have tried to figure out what I am doing wrong. I tried simplifying the query a bit (just to try and determine what part of the sql query was causing the problem) to only match the searchcriteria.category string with the varietycategory.category and the query returns the data set correctly.
Here is the working query (this query is simplified and insufficient):
SELECT DISTINCT categories.*, product.*
FROM (categories, product, product_category)
LEFT JOIN varietycategory ON varietycategory.productid = product.id
WHERE product_category.categoryid=4
AND product.id=product_category.productid
AND categories.category_id=product_category.categoryid
AND (varietycategory.category = 'color' OR varietycategory.category = 'size' OR varietycategory.category='shape');
But I also need to be able to match against the varietycategoryoptions as well.
Just to avoid confusion, I am only using searchcriteria to get the field category and use it as a string to match against the varietycategory.category
and I am only using searchcriteriaoption to get the field criteriaoption and use it as a string to match against varietycategoryoption.descriptor
Does anyone know what I am doing wrong with my 1st query?
Please do help as SQL is not expertise.
Thank you!
The error is at:
OR
(varietycategory.category = 'size' (varietycategoryoption.desciptor = 'small' OR varietycategoryoption.descriptor='medium'))
^
|
An operator (AND, OR) is missing here
This has nothing to do with the join syntax, by the way.
Do not mix implicit and explicit joins. Your query should look like:
SELECT DISTINCT c.*, p.*
FROM product_category pc join
categories c
on c.category_id = pc.categoryid join
product p
on p.id = pc.productid join
varietycategory vc
ON vc.productid = p.id
WHERE c.categoryid = 4 AND
vc.category in ('color', 'size', 'shape');
You probably don't need the distinct, but that depends on the data. The left join is unnecessary because you are filtering on the second table in the where.
A simple rule: Never use commas in the from clause. To help, MySQL has scoping rules that can cause queries to break when you mix implicit and explicit join syntax.
The problem was a misspelled field on the table varietycategory, which I named
vcid, when I almost always name my table primary key id's "id".

MySQL Join different tables

I am trying to join the following tables with the following code, but I can't join the last columns.
Table:magazine
id_mag **mag_name** id_freq
Table:frequency
id_freq **freq_name**
Table:copy
id_mag **id_copy** **copy_date** copy_price copy_page_number
Table:article
id_art **art_name** **art_page_number**
Table:copy_art
id_mag **id_copy** id_art article_page_num
I want to show a table with the following columns. The columns in the tables magazine, frequency, copy, article & copy_art that have ** ** are the ones I am interested in to be showed:
mag_name freq_name id_copy copy_date art_name art_page_number
I got the following table with this code:
SELECT * FROM magazine
JOIN frequency ON magazine.id_freq = frequency.id_freq
JOIN copy_art ON revista.id_mag=copy_art.id_mag
JOIN article ON copy_art.id_art=article.id_art
JOIN copy ON copy_art.id_copy=copy.id_copy;
Here is the translation for the name of each column that appears in the image:
id_rev = id_mag
nom_rev = mag_name
id_frec = id_freq
nom_frec = freq_name
id_rev = id_mag
id_ejem = id_copy
id_art = id_art
num_pag = article_page_num
nom_art = art_name
num_pag_art = art_page_number
fecha_ejem = copy_date
precio = copy_price
My doubt is the following:
What should I do in order to have the table with?
mag_name freq_name id_copy copy_date art_name article_page_num
Thanks a lot for your kindly support!
If you only want a few columns in the output, then you have to list which columns you do want. The key structure of the data is unclear (meaning it isn't clear which columns are the primary keys of each table); you have the id_mag and id_copy columns both appearing in copy and copy_art and it isn't entirely clear whether they're a composite key or id_copy is sufficient. Given that we don't have that information, we'll have to take your SELECT statement and its joins as gospel, but I'm not convinced that's correct.
You wrote:
SELECT *
FROM magazine
JOIN frequency ON magazine.id_freq = frequency.id_freq
JOIN copy_art ON revista.id_mag=copy_art.id_mag
JOIN article ON copy_art.id_art=article.id_art
JOIN copy ON copy_art.id_copy=copy.id_copy;
This collects all the columns from all the tables mentioned, which is wasteful. So, you need to specify which columns you do want:
SELECT m.mag_name, f.freq_name, c.id_copy, c.copy_date, a.art_name, a.art_page_number
FROM magazine AS m
JOIN frequency AS f ON m.id_freq = f.id_freq
JOIN copy_art AS y ON m.id_mag = y.id_mag
JOIN article AS a ON y.id_art = a.id_art
JOIN copy AS c ON y.id_copy = c.id_copy;
I'm not entirely sure that you need the copy_art table in the query, but I'm assuming you know your data better than I do.
You have to make sure that one of the first tables has got a foreign key for the articulo table to join that as well.
If you add that (For example in the revista table), you can make a JOIN over all tables with something like this:
SELECT * FROM revista
JOIN frecuencia ON revista.id_frec = frecuencia.id_frec
JOIN ejemplar ON revista.id_rev = ejemplar.id_rev
JOIN articulo ON revista.id_art = articulo.id_art;
See this fiddle for an example (I query * here, you can change that to just the columns that you need).

MYSQL get other table data in a join

I am currently running this SQL
SELECT jm_recipe.name, jm_recipe.slug
FROM jm_recipe
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
This returns the desired results except that I also need to return the name of the category that the recipe I am looking for is in, to do this I tried to add the field in to my SELECT statement and also add the table into the FROM clause,
SELECT jm_recipe.name, jm_recipe.slug, jm_category_name
FROM jm_recipe, jm_category
LEFT JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
WHERE jm_category_recipe.category_id = $cat"
However this just returns no results, what am i doing wrong?
You need to join both tables:
SELECT jm_recipe.name, jm_recipe.slug, jm.category_name
FROM jm_recipe
INNER JOIN jm_category_recipe ON jm_category_recipe.recipe_id = jm_recipe.id
INNER JOIN jm_category ON jm_recipe.recipe_id = jm_category.recipe_id
WHERE jm_category_recipe.category_id = $cat
I've changed the joins to inner joins as well. You might want to make them both LEFT joins if you have NULLs and want them in the result.
Also, you're vulnerable to SQL Injection by simply copying over $cat.
Here's some PHP specific info for you (I'm assuming you're using PHP.)

Correct MySQL JOIN format to avoid nested SELECT

I have two separate SELECT statements:
SELECT VCe.VId FROM `VCe` WHERE `YId` = 9007 AND `MaId` =76 AND `MoId` = 2851
SELECT r_pts.p_id FROM r_pts WHERE r_pts.v_id IN (57202, 57203, 69597, 82261, 82260, 69596, 69595, 82259)
When they are run separately they both complete in under .05sec however when I nest the first one within the second, it dramatically increases to 3.3sec.
I would like to do a join so that I can get the output from the second SELECT using the first select as the result set for the IN() but I cannot figure out how to include WHERE conditions in a JOIN.
Edit: Also what is the correct syntax to do a join as I am requesting?
Thanks for your help, its appreciated!
Equivalent to MattMcKnight's query whilst illustrating "how to include WHERE conditions in a JOIN":
SELECT r.p_id
FROM r_pts r
INNER JOIN VCe v
ON v.VId = r.v_id
AND
v.YId = 9007
AND
v.MaId = 76
AND
v.MoId = 2851
SELECT r_pts.p_id FROM r_pts, 'VCe' WHERE r_pts.v_id = VCe.VId AND VCe.YId = 9007 AND VCe.MaId =76 AND VCe.MoId = 2851
The basic goal of a join is to describe how the two tables relate. I inferred from your example that the v_id column in the r_pts table was a foreign key pointing to the VId primary key in the VCe table. When you add a term in the query (such as "r_pts.v_id = VCe.VId") that has a field from each table you wish to join, that tells the database how to match up the rows between the tables to make "virtual rows" that contain the columns from both tables. Your other query terms limit which rows are included in the result set.