create a result set difference between two tables in Mysql - php

I have two table suppose products and auto_assign_prod_list. I want to populate a dropdown list with the id of products table that are not present in auto_assign_prod_list table.
Suppose,
product table contain
Id
------
1
2
3
4
5
auto_assign_prod_list table contain
Id
-----
1
5
So, my result set will be
2
3
4
How is it possible using MySQL and PHP ?

Try this:
SELECT Id FROM product
WHERE Id NOT IN (SELECT Id FROM auto_assign_prod_list)
It will select the ids from product table which are not in auto_assign_prod_list table.
Result:
Id
------
2
3
4
See result in SQL Fiddle.

use a left join
select p.id
from products p
left join auto_assign_prod_list a on a.id = p.id
where a.id is null
SQLFiddle demo
See this great explanation of joins

Related

MYSQL multiple grouping with join

SELECT
p.product,
q.format,
p.title
FROM
product p
JOIN info q ON p.product = q.product
WHERE p.user='$user'
GROUP BY p.product,q.format
I want to first group by 'product' from the product table but the also by format on the info table.
This is to not show duplicates of format and product. At the moment only the grouping by product is working.
Table - products
product | title
0 one
1 two
1 two - a
2 three
Table - product_details
product | title | format |
0 one home
1 two home
1 two - a home
2 three work
So for this example I want a list like:
product | title | format
0 one home
2 three work
Instead of:
product | title | format
0 one home
1 two home
2 three work
After your table structures were posted, I can see what your intent is, I believe. It looks like you are attempting to limit your output result set to those values for product.product which are never repeated. That is, values for product.product which have exactly one product.title.
For that, you can use a GROUP BY aggregation to return only those with COUNT(*) = 1 after the group is applied.
In this case, since you only expect one row back per product.product anyway, you can do the aggregation at the top level, not requiring a subquery. If you had joined in other tables, and ended up getting multiple rows back per product due to other one-to-many relationships, you would need to use the subquery method instead (to be portable anyway - MySQL would still probably allow this)
SELECT
p.product,
q.format,
p.title
FROM
products p
JOIN product_details q ON p.product = q.product
GROUP BY
p.product,
q.format,
p.title
HAVING COUNT(*) = 1
Here is a demonstration: http://sqlfiddle.com/#!2/72eda/6
If you did expect multiple rows back per p.product, such as if you joined in additional one-to-many related tables, an efficient way to handle that is to perform a JOIN against a subquery that imposes that limit in the HAVING clause. Those which don't meet the HAVING condition won't be returned in the subquery and therefore get discarded by the INNER JOIN.
SELECT
p.product,
q.format,
p.title
FROM
products p
INNER JOIN product_details q ON p.product = q.product
/* Subquery returns only product values having exactly 1 row */
INNER JOIN (
SELECT product
FROM products
GROUP BY product
HAVING COUNT(*) = 1
) pcount ON p.product = pcount.product
WHERE p.user = '$user'
http://sqlfiddle.com/#!2/72eda/2

many-to-many relationship select checkboxes in form php

I have 3 tables: table with objects (A), table with properties (B) and a table with links object/property (A.id, B.id). The problem is that when I need to edit the object, I need to load data into the form, including the checkboxes state. As one of the possible solutions I see is to select data from the table with properties and from the table with objects and then write down the checkboxes using the nested loops, where the main loop will generate checkboxes and the subloop will be looking through the array of selections and will check the checkbox on id match, but I think there must be some way to select the data from the tables.
An example of data:
A.id B.id C(A.id B.id)
1 1 1 1
2 2 1 2
3 1 3
4 1 4
5
What I want to get is:
B.id A.id
1 1
2 1
3 1
4 1
5 NULL
So the B items with indexes 1,2,3,4 will be checked and 5 is unchecked. I've got this by using
SELECT DISTINCT B.id, A.id FROM B LEFT JOIN C ON B.id=C.id
WHERE A.id=<object id to edit> OR A.id IS NULL GROUP BY B.id
And it actually worked, but only for A.id=1. And with A.id=2 i've got
B.id A.id
5 NULL
Which means for me show only one unselected checkbox for property with id 5.
Instead of something like:
B.id A.id
1 NULL
2 NULL
3 NULL
4 NULL
5 NULL
With A.id=2. Is there any way to achieve this or maybe I should use different logic?
Instead of using WHERE clause, you can specify needed A.id in joining condition.
SELECT DISTINCT B.id, C.a_id FROM B LEFT JOIN C ON B.id=C.b_id AND C.a_id=2 GROUP BY B.id
Try this out here: http://sqlfiddle.com/#!2/68efa/13/0
You can use a CASE without using the WHERE clause
SELECT tableb.`id`,
(CASE WHEN tablec.`aid`=2 THEN tablec.`aid` ELSE NULL END ) AS test
FROM tableb
LEFT JOIN tablec ON (tableb.`id` = tablec.`bid`)
Fiddle for id=2
Fiddle for id=1
It will work and gives you result in all conditions that you have the matched ids or not

Fetch all rows data from second table using single join query

I have run into a 1-N situation. i.e 1 record in 1st table will have multiple records in second table, I just wanna fetch all data corresponding to the ID in 1st table using joins, is this possible.
table 1 : ID name
1 pradeep
table 2: ID table1_id orders
1 1 23
2 1 25
3 1 26
In a single query i should get all records. I don't wanna loop as i am doing it and its taking lot of time.
I want to display user html output in manner like this. So there lies the problem.
ID Name orders1 orders2 orders order4
SELECT
*
FROM
table2
LEFT JOIN
table1 ON
table1.ID = table2.table1_id
SELECT
t2.* /* fetch data from second table */
FROM
table1 t1
LEFT JOIN table2 t2 on t2.table1_id = t1.id
WHERE t1.id = <id>;
I wouldn't recomment it though. Why don't you just run it as 2 separate queries?

Mysql query to get parent details in a single query

I have a table where i store categories with its parent's id. Following is the table structure
What i need is to get the parent and details of id 4 in a single query without php recursion
id | CategoryName | parentid
1 Web 0
2 Software 0
3 PHP 1
4 Arrays 3
A self join should be sufficient here. Your goal is to join the table against itself, while relating the parentid of the main row to the id of its parent's row.
SELECT
me.id AS me_id,
me.CategoryName AS me_category,
parent.id AS parent_id,
parent.CategoryName AS parent_category
FROM
tablename me JOIN tablename parent ON me.parentid = parent.id
WHERE me.id = 4
Would a variation of
select * from categories t1 join categories t2 where t1.parentid=t2.id
work for you

sorting by value in another table php mysql

I have two tables, one called episodes, and one called score. The episode table has the following columns:
id | number | title | description | type
The score table has the following columns:
id | userId | showId | score
The idea is that users will rate a show. Each time a user rates a show, a new row is created in the score table (or updated if it exists already). When I list the shows, I average all the scores for that show ID and display it next to the show name.
What I need to be able to do is sort the shows based on their average rating. I've looked at joining the tables, but haven't really figured it out.
Thanks
To order the results, use and ORDER BY clause. You can order by generated columns, such as the result of an aggregate function like AVG.
SELECT e.title, AVG(s.score) AS avg_score
FROM episodes AS e
LEFT JOIN scores AS s ON e.id=s.showId
GROUP BY e.id
ORDER BY avg_score DESC;
You're right. You have to JOIN these tables, then use GROUP BY on the 'episodes' table's 'id' column. Then you'll be able to use AVG() function on 'the scores' tables's 'score' column.
SELECT AVG(scores.score) FROM episodes LEFT JOIN scores ON scores.showId = episodes.id GROUP BY episodes.id
SELECT episodes.*, AVG(score.score) as AverageRating FROM episodes
INNER JOIN score ON (episodes.id = score.showId)
GROUP BY episodes.id
ORDER BY AVG(score.score) DESC

Categories