Is there an alternative for MYSQL HAVING - php

I'm trying to find some records based on the tags they have. In order to find out which tags a record has i add them to the result using a subquery. To find out which results should be returned i added a having statement on the end of the query. But something tells me this is not the best way.
SELECT e.id, e.title, e.text, e.introduction,
UNIX_TIMESTAMP(e.starts_on) AS starts_on,
UNIX_TIMESTAMP(e.ends_on) AS ends_on,
m.id AS meta_id,
m.url,
cm.title AS category_title,
cm.url AS category_url,
CONCAT(
",",
(
SELECT GROUP_CONCAT(t.id)
FROM modules_tags AS mt
JOIN tags AS t ON t.id = mt.tag_id
WHERE mt.other_id = e.id
),","
) AS tags_search
FROM event_posts AS e
INNER JOIN meta AS m ON e.meta_id = m.id
LEFT JOIN event_categories AS c ON e.category_id = c.id
LEFT JOIN meta AS cm ON c.meta_id = cm.id
LEFT JOIN modules_tags AS mt ON mt.other_id = e.id
LEFT JOIN tags AS t ON t.id = mt.tag_id
WHERE 1 HAVING tags_search LIKE '%,5,%' AND tags_search LIKE '%,6,%'

FIND_IN_SET() is the best way to find values in comma separated values in MySQL.

Related

Having issues with this Mysql query

Hello i'm learning sql and i have some issues with joins(which i have problems understanding them)
I have this issue
#1066 - Not unique table/alias: 'tbl_respuestas'
what the query supposed to do, is count how many people(general,ignore user) has answer 'x', in 'y' question of 'z' survey
SELECT COUNT(*) FROM tbl_respuestas
INNER JOIN tbl_encuesta_usuario ON tbl_encuesta_usuario.user_id = user.id
INNER JOIN tbl_encuesta ON tbl_encuesta.id = tbl_encuesta_usuario.tbl_encuesta_id
INNER JOIN tbl_encuesta_has_tbl_preguntas ON tbl_encuesta_has_tbl_preguntas.tbl_encuesta_id = tbl_encuesta.id
INNER JOIN tbl_preguntas ON tbl_preguntas.id = tbl_encuesta_has_tbl_preguntas.tbl_preguntas_id
INNER JOIN tbl_preguntas_has_tbl_respuestas ON tbl_preguntas_has_tbl_respuestas.tbl_preguntas_id = tbl_preguntas.id
INNER JOIN tbl_respuestas ON tbl_respuestas.id = tbl_preguntas_has_tbl_respuestas.tbl_respuestas_id
WHERE tbl_respuestas.respuesta = 2
line SELECT COUNT(*) FROM tbl_respuestas
and line INNER JOIN tbl_respuestas
does not makes sense, hence the error.
Unless it is what you want then you need to give then different name/alias like below:
SELECT COUNT(*) FROM tbl_respuestas r
INNER JOIN tbl_respuestas r2
Also as a quick note you can rewrite the entire sql like below.
It is good practice to give your tables a name for shorter referencing and makes the sql look a little cleaner.
Also if both tables you are trying to join has the same column name then you can use the keyword USING instead of having to write that long line tbl_encuesta_usuario.user_id = user.id
Please be sure to put r and r2 in its prope place
SELECT COUNT(*) FROM tbl_respuestas r
INNER JOIN tbl_encuesta_usuario u USING user_id
INNER JOIN tbl_encuesta e ON e.id = u.tbl_encuesta_id
INNER JOIN tbl_encuesta_has_tbl_preguntas hp ON hp.tbl_encuesta_id = e.id
INNER JOIN tbl_preguntas p ON p.id = hp.tbl_preguntas_id
INNER JOIN tbl_preguntas_has_tbl_respuestas hr ON hr.tbl_preguntas_id = p.id
INNER JOIN tbl_respuestas r2 ON r2.id = hr.tbl_respuestas_id
WHERE r.respuesta = 2

Left join not working in my prepared statement (mysqli)

I can't get a left join to work in my prepared statement.
"SELECT DISTINCT(a.auto_id), m.merk, a.model, a.uitvoering, a.standaardtekst, a.prijs, a.prijs2, a.prijs3, a.handelsprijs, a.aanmaak, s.soort, z.prijs_id
/*,GROUP_CONCAT(DISTINCT(apc.NL) ORDER BY apc.NL ASC)*/
FROM autocom_new.auto_new a
INNER JOIN autocom_new.tbl_merken m
ON a.merk = m.merk_id
INNER JOIN autocom_new.tbl_soort s
ON a.soort = s.soort_id
INNER JOIN autocom_new.auto_zoekmachines z
ON a.auto_id = z.auto_id
/*
LEFT JOIN autocom_new.auto_accessoire acc
ON a.auto_id = acc.auto_id
LEFT JOIN autocom_new.tbl_autopricecode_new apc
ON acc.code_id = apc.code_id
*/
WHERE a.ac LIKE ? AND a.flag = ?"
The commented parts are the parts that aren't working.
I have no idea what I'm doing wrong.
EDIT
First of all I forgot that both tables have a column ac, so I've changed the where statement a bit. The left joins are working now, but the part in the select is still not working
So the problem was that I forgot a GROUP BY.
"SELECT DISTINCT(a.auto_id), m.merk, a.model, a.uitvoering, a.standaardtekst, a.prijs, a.prijs2, a.prijs3, a.handelsprijs, a.aanmaak, s.soort, z.prijs_id,
GROUP_CONCAT(DISTINCT(apc.NL) ORDER BY apc.NL ASC)
FROM autocom_new.auto_new a
INNER JOIN autocom_new.tbl_merken m
ON a.merk = m.merk_id
INNER JOIN autocom_new.tbl_soort s
ON a.soort = s.soort_id
INNER JOIN autocom_new.auto_zoekmachines z
ON a.auto_id = z.auto_id
LEFT JOIN autocom_new.auto_accessoire acc
ON a.auto_id = acc.auto_id
LEFT JOIN autocom_new.tbl_autopricecode_new apc
ON acc.code_id = apc.code_id
WHERE a.ac LIKE ? AND a.flag = ?
GROUP BY a.auto_id"

retrieving values from multiple tables in mysql

I am using php and I have to get the data from multiple tables with common id, but the problem is that in few tables that common id contains multiple records,using inner join gives me separate rows of data e.g.
{"dish_id":"52","quantity":"1","STATUS":"pending","franchise_id":"5","order_type":"PickUp","extraId":"2"}
{"dish_id":"52","quantity":"1","STATUS":"pending","franchise_id":"5","order_type":"PickUp","extraId":"3"}
extraId is the multiple record for the dish_id:52.
I need result like this.
{"dish_id":"52","quantity":"1","STATUS":"pending","franchise_id":"5","order_type":"PickUp","extraId"[{"id":"2"},{"id":"3"]}}
My query is:
$orders = "Select DISTINCT order_detail.dish_id,order_detail.quantity,order_detail.STATUS,
order_main.franchise_id,order_main.order_type,
order_extras.extra_id,order_extras.extra_title,
order_addons.addon_id,order_addons.addon_size
from order_main
INNER JOIN order_detail ON order_main.id=order_detail.order_id
INNER JOIN order_extras ON order_main.id=order_extras.order_id
INNER JOIN order_addons ON order_main.id=order_addons.order_id
WHERE order_main.franchise_id='$storeId'
and
order_detail.STATUS!='$order_status'";
please help.
Use group by and group_concat. Something like this:
Select d.dish_id, d.quantity, d.STATUS, m.franchise_id, m.order_type,
group_concat(e.extra_id) as extraids
from order_main m INNER JOIN
order_detail d
ON m.id = d.order_id INNER JOIN
order_extras e
ON m.id = e.order_id INNER JOIN
order_addons a
ON m.id = a.order_id
where m.franchise_id = '$storeId' and d.STATUS <> '$order_status'
group by d.dish_id, d.quantity, d.STATUS, m.franchise_id, m.order_type;
Your desired results do not include these columns:
e.extra_title
a.addon_id
a.addon_size
I would also suggest that you remove the join to order_addons.
Notice that table aliases make the query easier to write and to read.
You can use group bywith dish_id
$orders = "Select DISTINCT order_detail.dish_id,order_detail.quantity,order_detail.STATUS,
order_main.franchise_id,order_main.order_type,
order_extras.extra_id,order_extras.extra_title,
order_addons.addon_id,order_addons.addon_size
from order_main
INNER JOIN order_detail ON order_main.id=order_detail.order_id
INNER JOIN order_extras ON order_main.id=order_extras.order_id
INNER JOIN order_addons ON order_main.id=order_addons.order_id
WHERE order_main.franchise_id='$storeId'
and
order_detail.STATUS!='$order_status' group by order_detail.dish_id";

Attempting to add count function to a complex query PHP MYSQL

I have a complex query consisting of lots of Inner and Left Joins and i am attempting to get the number of record back in a certain table using the COUNT Function of SQL.
I am attempting to get the number of records in the 'held_proposals' table for each proposal using the proposal_id since I'll be outputting the data into a table using a foreach loop.
In essence I would like to show how many students have 'held' a proposal against each proposal.
This was my attempt:
SELECT p.proposal_id, p.proposal_title, p.description, u.user_record_id, u.forename, u.surname, c.course_title, h.*,
GROUP_CONCAT(DISTINCT t.tag_title) AS tags FROM proposal p
LEFT JOIN user u on u.user_record_id = p.user_record_id
LEFT JOIN course_details c on c.course_code = p.course_code
LEFT JOIN record r on r.proposal_id = p.proposal_id
LEFT JOIN proposal_tags pt on pt.proposal_id = p.proposal_id
LEFT JOIN tag_details t on t.tag_code = pt.tag_code
LEFT JOIN (
SELECT h.student_record_id, COUNT(*) AS Held
FROM held_proposals h
) H on h.proposal_id = p.proposal_id
WHERE p.source = "Supervisor"
AND (r.status_code not in (3,8) OR r.status_code IS NULL)
GROUP BY p.proposal_id;
the table currently looks like this:
I would like to add the value returned from the 'held_proposals' table for each proposal at the end of the table as another column.
Could any please provide me with some guidance as to how I can achieve this in the SQL query. Thank you in advance.
You need to group the count inside the query which you are joining something as
SELECT
p.proposal_id,
p.proposal_title,
p.description,
u.user_record_id,
u.forename,
u.surname,
c.course_title, coalesce(h.Held,0) as `Held`,
GROUP_CONCAT(DISTINCT t.tag_title) AS tags
FROM proposal p
LEFT JOIN user u on u.user_record_id = p.user_record_id
LEFT JOIN course_details c on c.course_code = p.course_code
LEFT JOIN record r on r.proposal_id = p.proposal_id
LEFT JOIN proposal_tags pt on pt.proposal_id = p.proposal_id
LEFT JOIN tag_details t on t.tag_code = pt.tag_code
LEFT JOIN (
SELECT proposal_id, COUNT(*) AS Held
FROM held_proposals group by proposal_id
) h on h.proposal_id = p.proposal_id
WHERE p.source = "Supervisor"
AND (r.status_code not in (3,8) OR r.status_code IS NULL)
GROUP BY p.proposal_id;

mysql join return 0 for one column with other columns intact

I wish to join multiple tables like- Categories, menus, restaurants, reviews, etc.
to return the restaurants that provide the inserted food with their prices.
Everything works except numberOfReviews in reviews table.
If a restaurant has no reviews then output should be 0 for numOfReviews column but other column values should be retrieved i.e. price, name, etc.
With following query I get all fields as null and count(numReviews) as 0:
select r.id
,r.`Name`
,r.`Address`
,r.city
,r.`Rating`
,r.`Latitude`
,a.`AreaName`
,m.`Price`
,count(rv.id)
from `categories` c, `menus` m, `restaurants` r, areas a, reviews rv
where m.`ItemName`="tiramisu"
and c.`restaurant_id`=r.`id`
and m.`category_id`=c.id
and r.`AreaId`=a.`AreaId`
and if I can't match rv.restaurant_id=r.id in where clause(obviously).
Where am I getting wrong? How do I solve this?
edited
select r.id,
r.`Name`,
r.`Address`,
r.city,
r.`Rating`,
r.`Latitude`,
a.`AreaName`,
m.`Price`,
r.`Longitude`,
r.Veg_NonVeg,
count(rv.id)
from restaurants r LEFT JOIN `reviews` rv on rv.`restaurant_id`=r.`id`
inner join `categories` c on c.`restaurant_id` = r.id
inner join `menus` m on m.`category_id` = c.id
inner join `areas` a on a.`AreaId` = r.`AreaId`
where m.`ItemName`="tiramisu"
First of all, don't use this old school syntax for the jointures.
Here is a query that may solve your problem:
SELECT R.id
,R.Name
,R.Address
,R.city
,R.Rating
,R.Latitude
,R.Longitude
,A.AreaName
,M.Price
,R.Veg_NonVeg
,COUNT(RV.id) AS numOfReviews
FROM restaurants R
INNER JOIN categories C ON C.restaurant_id = R.id
INNER JOIN menus M ON M.category_id = C.id
INNER JOIN areas A ON A.AreaId = R.AreaId
LEFT JOIN reviews RV ON RV.restaurant_id = R.id
WHERE M.ItemName = 'tiramisu'
GROUP BY R.id, R.Name, R.Address, R.city, R.Rating, R.Latitude, R.Longitude, A.AreaName, M.Price, R.Veg_NonVeg
I used explicit INNER JOIN syntax instead of your old school syntax and I modified the jointure with table reviews in order to get the expected result. The GROUP BY clause is required to use the aggregate function COUNT, every rows will be grouped by the enumerated columns (every column except the one used by the function).
Here is another solution that simplify the GROUP BY clause and allow the modification of SELECT statement without having to worry about the fact that every columns need to be part of the GROUP BY clause:
SELECT R.id
,R.Name
,R.Address
,R.city
,R.Rating
,R.Latitude
,R.Longitude
,A.AreaName
,M.Price
,R.Veg_NonVeg
,NR.numOfReviews
FROM restaurants R
INNER JOIN (SELECT R2.id
,COUNT(RV.id) AS numOfReviews
FROM restaurants R2
LEFT OUTER JOIN reviews RV ON RV.restaurant_id = R2.id
GROUP BY R2.id) NR ON NR.id = R.id
INNER JOIN categories C ON C.restaurant_id = R.id
INNER JOIN menus M ON M.category_id = C.id
INNER JOIN areas A ON A.AreaId = R.AreaId
WHERE M.ItemName = 'tiramisu'
As you can see here I added a new jointure on a simple subquery that does the aggregation job in order to provide me the expected number of reviews for each restaurant.
Hope this will help you.

Categories