How to select few values with and condition? - php

I have table example http://prntscr.com/msqpep
I need empty result when i am doing
SELECT * FROM prods
WHERE prod_id = 3 and (fet_id = 1 and fet_id = 5)
but that code so not work (fet_id = 1 and fet_id = 5) or (fet_id = 1 and fet_id = 3)
"Where in" is a best way but i need `WHERE IN(1 and 2 and 3)
By default "WHERE IN" working as (1 or 2 or 3)
When I select fet_id=1 and fet_id=3 i need two results
When i select fet_id=1 and fet_id=5 i need no result

You probably want
SELECT prod_id FROM prods GROUP by prod_id
HAVING (SUM(fet_id=1)>0
AND SUM(fet_id=5)>0)
OR
(SUM(fet_id=1)>0
AND SUM(fet_id=3)>0)
HAVING filters groups WHERE filters rows.

Try This:
SELECT p1.id AS id1, p2.id AS id2
FROM `prods` p1 LEFT JOIN `prods` p2 ON p1.`prod_id` = p2.`prod_id`
WHERE p1.`fet_id` = '1' AND p2.`fet_id` = '3'
Output
id1 id2
1 3
With input fet_id=1 & fet_id=5
SELECT p1.id AS id1, p2.id AS id2
FROM `prods` p1 LEFT JOIN `prods` p2 ON p1.`prod_id` = p2.`prod_id`
WHERE p1.`fet_id` = '1' AND p2.`fet_id` = '5'
Output: No result

And another one if need more then two values
SELECT res.* FROM (SELECT 3 as total,
(SELECT COUNT(*) FROM `prods` as t1 WHERE t1.`fet_id` = 1 OR t1.`fet_id` = 2 OR t1.`fet_id` = 5) as current,
t2.*
FROM `prods` as t2 WHERE t2.`fet_id` in (1,2,5)) as res WHERE res.total = res.current

Related

SELECT product variants SQL

This is my query without variant options
SELECT p.*, pd.`name` AS `product_name`
FROM `product` AS `p`
LEFT JOIN `product_description` AS `pd` ON p.`id` = pd.`product_id`
LEFT JOIN `product_to_variant` AS `pv` ON p.`id` = pv.`product_id`
WHERE p.`status` = 0
GROUP BY p.`id`
ORDER BY p.`id` DESC;
SQLFiddle: http://sqlfiddle.com/#!9/8955b/5
and the follwing query has variant options but it doesn't work
SELECT p.*, pd.`name` AS `product_name`
FROM `product` AS `p`
LEFT JOIN `product_description` AS `pd` ON p.`id` = pd.`product_id`
LEFT JOIN `product_to_variant` AS `pv` ON p.`id` = pv.`product_id`
WHERE p.`status` = 0
AND (pv.`feature_id` = 2 AND pv.`variant_id` = 6)
AND (pv.`feature_id` = 3 AND pv.`variant_id` = 11)
GROUP BY p.`id`
ORDER BY p.`id` DESC;
and I also trying to query but there is no output
SELECT pv.* FROM `product_to_variant` AS `pv`
WHERE (pv.`feature_id` = 2 AND pv.`variant_id` = 2)
AND (pv.`feature_id` = 3 AND pv.`variant_id` = 11)
Do you have any other idea how to receive the products: 14, 15 by specific variant_id 6 AND 11 http://prntscr.com/ect2oh
Here is one method to do what you want:
SELECT p.*, pd.name AS product_name
FROM product p LEFT JOIN
product_description pd
ON p.id = pd.product_id JOIN
product_to_variant pv
ON p.id = pv.product_id
WHERE p.status = 0 AND
((pv.feature_id = 2 AND pv.variant_id = 6) OR
(pv.feature_id = 3 AND pv.variant_id = 11)
)
GROUP BY p.id
HAVING COUNT(DISTINCT feature_id) = 2
ORDER BY p.id DESC;
Notes:
No row can meet your original conditions. Because a column cannot have two values at the same time. Hence the OR rather than AND.
The HAVING clause checks that both values match.
There is no need for a LEFT JOIN to pv, because you are checking values from that table in the WHERE clause -- there have to be matches.
The LEFT JOIN to pa is probably also unnecessary.
Using backticks everywhere just makes the query harder to write and to read.
Maybe like this:
SELECT pv.* FROM `product_to_variant` AS `pv`
WHERE (pv.`feature_id` = 2 AND pv.`variant_id` = 2)
OR (pv.`feature_id` = 3 AND pv.`variant_id` = 11)
Instead of AND, which says, you need both feature_id and variant_id in the results, use OR because it takes both.

How to group by a column with forloop and union all

Hi this is my query from this query i am getting 3 records i want only one record and i am trying to group by studentid
foreach ($gdFinaldata['gdskill'] as $skillId => $skillScore){
$filterQuery .= $union_all. "SELECT stu.student_pid
FROM tbl_students stu LEFT JOIN r_job_invitations jbi ON stu.student_email = jbi.email
LEFT JOIN r_job_scores jsc ON jsc.student_id = stu.student_pid
WHERE job_id = ".$jobID." AND skill_id = ".$skillId." AND gd_score >= ".$skillScore." ";
$union_all=" UNION ALL ";
} //for ends here
the recodrs will come like this:
SELECT stu.student_pid FROM tbl_students stu LEFT JOIN r_job_invitations jbi ON stu.student_email = jbi.email LEFT JOIN r_job_scores jsc ON jsc.student_id = stu.student_pid WHERE job_id = 88 AND skill_id = 3 AND gd_score >= 1
UNION ALL
SELECT stu.student_pid FROM tbl_students stu LEFT JOIN r_job_invitations jbi ON stu.student_email = jbi.email LEFT JOIN r_job_scores jsc ON jsc.student_id = stu.student_pid WHERE job_id = 88 AND skill_id = 63 AND gd_score >= 2
UNION ALL
SELECT stu.student_pid FROM tbl_students stu LEFT JOIN r_job_invitations jbi ON stu.student_email = jbi.email LEFT JOIN r_job_scores jsc ON jsc.student_id = stu.student_pid WHERE job_id = 88 AND skill_id = 128 AND gd_score >= 3
After this i want to add group by how can i do that i tried like this:
$groupby = "GROUP BY student_id";
$filterStudents = $conn->query($filterQuery.$groupby);
My issue is still returning 3 records i want to group by student
For Reference:
There are several ways to do this.
Use union instead of union all, this will retain only unique entries
select ...
union
select ...
union
select ...
If you want to keep union all (why do you?), use parenthesis around your selects and append group by after it
select student_pid
( select student_pid, student_id from ...
union all
select student_pid, student_id from ...
union all
select student_pid, student_id from ... ) as t
group by student_id
Your PHP would then look like
foreach (...) {
$filterQuery .= $union_all. "SELECT stu.student_pid, jsc.student_id ..."
// ...
}
$outerQuery = "select student_pid ("
$groupby = ") as t GROUP BY student_id";
$filterStudents = $conn->query($outerQuery . $filterQuery . $groupby);
Instead of group by, you can also use distinct, e.g.
select distinct student_pid
( select student_pid from ...
union all
select student_pid from ...
union all
select student_pid from ... ) as t
Collect the result in an array and then use array_unique
Although this is the least efficient, since it fetches all entries instead of the relevant parts.

invalid records using inner join from two tables

I have this sql statement generated from codeigniter
SELECT * FROM (`products`) LEFT JOIN `products_attributes` ON `products_attributes`.`product_id` = `products`.`id` WHERE `products`.`category` = '1' AND `products`.`sub_category` = '1' AND `products_attributes`.`attribute_id` = '3' AND `products_attributes`.`attribute_id` = '4' AND `products_attributes`.`attribute_id` = '5' GROUP BY `products`.`id`
and I have these tables
products :
products_attributes :
I need to get the products with the all attributes only, so I will get the product id = 1 if the attributes are 3,4,5 and if the attributes are 3,4,5,6 I will not get product id = 1
Your sql query is totally wrong. What you did is:
Give me the record the attribute_id = 3 AND attribute_id = 4 AND attribute_id = 5 AND attribute_id = 6. One row can not be equal to 3 and 4 at the same time.
What you need can be achieved in many different ways. For example:
SELECT
products.id
FROM products
JOIN products_attributes ON products_attributes.product_id = products.id
WHERE
products.category = '1'
AND `products_attributes`.`attribute_id` IN (3,4,5,6)
GROUP BY
products.id
HAVING COUNT(DISTINCT `products_attributes`.`attribute_id`) = 4
If you specify just IN ... then it will take all the records who has at least 1 such attribute_id
Try this:
SELECT * FROM (`products`)
LEFT JOIN `products_attributes`
ON `products_attributes`.`product_id` = `products`.`id`
WHERE `products`.`category` = 1
AND `products`.`sub_category` = 1
AND `products_attributes`.`attribute_id` IN (3, 4, 5)
GROUP BY `products`.`id`

How to make an Order By a field but with a condition inside?

Please masters, I have three table, that I need to select data from using a LEFT JOIN;
and that I need to order by a field q (that exists in table3) but only where state = 1 (that exists also in table3).
I tried this but it doesn't work :
SELECT * FROM table 1
LEFT JOIN table2 ON x = y
LEFT JOIN table3 ON z=w
WHERE w = 1
ORDER BY q IN ( SELECT q FROM table3 WHERE state = 1);
Please any suggestions ?
How abt this:
SELECT * FROM table 1
LEFT JOIN table2 ON x = y
LEFT JOIN table3 ON z=w
WHERE w = 1
ORDER BY case when state=1 then 0 else 1 end,q
Try this:
SELECT *,
(SELECT q FROM table3 WHERE state = 1) as sort_order
FROM table 1
LEFT JOIN table2 ON x = y
LEFT JOIN table3 ON z=w
WHERE w = 1
ORDER BY sort_order
As I do not know what the desired result should be, possibly this is the right query:
SELECT *
FROM table1 as t1
LEFT JOIN table2 as t2 ON t1.x = t2.y
LEFT JOIN table3 as t3 ON t2.z = t3.w AND t3.state = 1
WHERE t3.w = 1
ORDER BY t3.q
Try something like that :
SELECT * FROM table 1
LEFT JOIN table2 ON x = y
LEFT JOIN table3 ON z=w
WHERE w = 1 AND table3.state = 1
ORDER BY q

MySQL: OUTER JOIN and COUNT()

I have table 'posters', table 'reviews' and table 'trailers'. Every table is connected with an movieID column, but each table can be empty for certain movieIDs:
++ posters_table +++ ++ reviews_table ++ ++ trailers_table ++
--itemID--+--filename- --itemID--+--review-- --itemID--+--trailer
---------------------- --------------------- ---------------------
----001---+--0012343-- ----004---+--blalba-- ----002---+--002345--
----001---+--0013331-- ----004---+--xlalxa-- ----005---+--005434--
----002---+--0020052-- ----005---+--zlalza-- ----001---+--005335--
I want to COUNT() the number of posters, reviews and trailers for the specified movieID and get 0 if no available.
So if I want to count movieID = 001 I get: ['posters'] = 2 / ['reviews'] = 0 and ['trailers'] = 1 (for example)
Can someone post the SQL query to do this?
select
(select count(*) from posters_table where itemId = ?) as posters,
(select count(*) from reviews_table where itemId = ?) as reviews,
(select count(*) from trailers_table where itemId = ?) as trailers;
I think if you JOIN the movie table to a result set that gives the count, you can then pick out whether or not the count is > 0 and give the appropriate value:
SELECT movieID, IF(posters.posters_count > 0, posters.posters_count,0) AS posters_total, IF(reviews.reviews_count > 0, reviews.reviews_count,0) AS reviews_total, IF(trailers.trailers_count > 0, trailers.trailers_count,0) AS trailers_total
FROM movies m
LEFT JOIN (SELECT itemID,COUNT(*) AS posters_count FROM posters_table WHERE itemID = '001' GROUP BY itemID) posters ON posters.itemID = movies.movieID
LEFT JOIN (SELECT itemID,COUNT(*) AS reviews_count FROM reviews_table WHERE itemID = '001' GROUP BY itemID) reviews ON reviews.itemID = movies.movieID
LEFT JOIN (SELECT itemID,COUNT(*) AS trailers_count FROM trailers_table WHERE itemID = '001' GROUP BY itemID) trailers ON trailers.itemID = movies.movieID
WHERE m.movieID = '001'
EDIT: I prefers ar's solution. Much simpler!
select
(select count(P.movieid) from posters P where P.movieid=1),
(select count(R.movieid) from reviews R where R.movieid=1),
(select count(T.movieid) from trailers T where T.movieid=1)
The tables are not "really" joined so you need three selects.

Categories