Find uncommon data from two tables in mysql - php

i am using a category , product relation to find data. I am in situation like i have a category table and product table with categoryid and product type. No suppose i have a particular type and i want to find those category which a product of a specific type does not have.
Table struture are like
Category Table
____________
|Id|Category|
| 1| X |
_____________
Product Table
____________________________
|ID | Product|Category| Type|
| 1 | Y | 1 | 2 |
_____________________________
I can find it by using a sub query like
SELECT *
FROM category
WHERE id NOT IN(SELECT category
FROM product
WHERE type = 2);
Is there a way to get it by another way
I also use a JOIN like
SELECT *
FROM category AS c
JOIN products AS p
ON c.id <> p.category
WHERE p.type = 2
Why does this not give the appropriate result.

Use LEFT JOIN and use IS NULL predicate:
SELECT *
FROM category AS c
LEFT JOIN products AS p
ON c.id = p.category
AND p.type = 2
WHERE p.category IS NULL;
The unmatched rows from the second table will have null values in the category field, the WHERE p.category IS NULL will filter and give you them

Related

MySQL WHERE filter based on subquery in SELECT

I have a table named Records that shows products. I also have a table named Categories that shows the categories for each individual product (if one exists).
The Categories table is structured liked:
id category_id
-- -----------
1 1
1 3
3 1
3 2
5 4
The query I run to pull record ID and category ID(s) is:
SELECT
Records.id,
(SELECT
GROUP_CONCAT(C.category_id)
FROM `Categories` C
WHERE Records.id = C.id) AS 'CategoryName'
FROM
Records
The output will return:
id CategoryName
-- ------------
1 1,3
2 NULL
3 1,2
4 4
5 NULL
I have an area of my website where users can filter records by category. Let's say user wants to filter for category = 1 or 2. I was thinking I just tack on a WHERE FIND_IN_SET(1,CategoryName) OR FIND_IN_SET(2,CategoryName) but this does not work because of the MySQL execution order and CategoryName column does not exist yet.
What is the best way to filter for category_id? The input for categories will be comma separated but I can use PHP to explode() the string to separate them.
You can rewrite the query with a LEFT join of Records to Categories:
SELECT r.id,
GROUP_CONCAT(c.category_id) AS CategoryName
FROM Records r LEFT JOIN Categories c
ON c.id = r.id
GROUP BY r.id
and if you want to use the same query for filtering all you have to do is add at the end a HAVING clause:
HAVING FIND_IN_SET(1, CategoryName) OR FIND_IN_SET(2, CategoryName)
Or, you can filter first and then aggregate:
SELECT r.id,
GROUP_CONCAT(c.category_id) AS CategoryName
FROM Records r INNER JOIN Categories c
ON c.id = r.id
WHERE c.category_id IN (1, 2)
GROUP BY r.id

Mysql user subscription query fails

I have a database named socialnetwork and has 5 tables category , post_category , posts , subscribe , user.
my table structures
-------- -------------
category posts
-------- ------------
categoryID postID
categoryName post
userID
categoryID
-------------- ---------------
post_category subscribe
--------------- ---------------
postID subscriberID
categoryID categoryID
--------------
usertable
--------------
userID
userName
data's in the table
category table usertable
-------------------------- -------------------
categoryID categoryName userID userName
--------------------------- --------------------
1 film 1 jijojohn32
2 television 2 sijojohn
posts_category table subscribe table
------------------ -------------------------
postID categoryID subscriberID categoryID
--------------------- ------------------------
1 1 1 1
1 2 1 2
2 2 2 2
posts table
---------------------------------------------------
postID post userID categoryID
--------------------------------------------------
1 this post is cool 1 1
2 demo post 2 2
User 1 can subscribe to different categories and he can see the articles in the categories he subscribes. That's what i am trying to implement here. And i have this query but it's not giving me the result i want.
USE socialnetwork;
SELECT socialnetwork.usertable.userName,socialnetwork.posts.post, GROUP_CONCAT(socialnetwork.category.categoryName) as category
FROM socialnetwork.category
INNER JOIN subscribe
ON subscribe.categoryID = category.categoryID
INNER JOIN posts
ON posts.categoryID = subscribe.categoryID
INNER JOIN usertable
ON usertable.userID = posts.userID
INNER JOIN socialnetwork.post_category
ON post_category.postID = posts.postID
WHERE subscriberID = "1"
GROUP BY socialnetwork.category.categoryName
Here's the result i am getting
---------------------------------
username post category
----------------------------------
jijojohn32 this post is cool film, film
sijojohn demo post television
The result i want
---------------------------------------------
username post category
-------------------------------------------
jijojohn32 this post is cool film,television
sijojohn demo post television
I want the post from the categories he subscribed to , the username of the user posted the articles , and categories which posts reside. What's wrong in my query ?. any idea ?. thanks
You are not aggregating by the right columns. I think this is the query that you want:
SELECT ut.userName, p.post, GROUP_CONCAT(c.categoryName) as category
FROM socialnetwork.category c INNER JOIN
subscribe s
ON s.categoryID = c.categoryID INNER JOIN
posts p
ON p.categoryID = s.categoryID INNER JOIN
usertable ut
ON ut.userID = p.userID INNER JOIN
socialnetwork.post_category pc
ON pc.postID = p.postID
WHERE subscriberID = 1
GROUP BY ut.userName, p.post;
Here's the working query. I made some modifications in the table. Deleted the categoryID from posts. Made a new table called post_category.
--------------
post_category
-------------
postID
categoryID
Here's the query
SELECT GROUP_CONCAT(category.categoryName) as category , category.categoryID , subscribe.subscriberID , posts.post ,
usertable.userName
from category
INNER JOIN subscribe
ON subscribe.categoryID = category.categoryID
INNER JOIN post_category
ON category.categoryID = post_category.categoryID
INNER JOIN posts
ON posts.postID = post_category.postID
INNER JOIN usertable
ON usertable.userID = posts.userID
WHERE subscriberID = 1
GROUP BY post_category.postID
There exists a conflict
Category table consists of
Category id and Category Name
Post Table consists of
Post id and Corresponding Category Id
As well as
Post_Category table consists of
Post id and Category Id
Hence it is picking from the Posts table, that
Row 1 - has only 1 category id associated with it
I suggest you remove Category id from Posttable
It is pointless to have 2 keys in 1 table, and similar 2 keys in other table.
Try to establish Primary key Foreign key relationship.
Hope that helps

MQL, PHP select all from two tables?

So i have two tables:
order_product
--------------------------------------------------
| ProductID | Quantity
--------------------------------------------------
products
-------------------------------------------------------------
| ProductID | productname | Desc | Price | Stock | Image
------------------------------------------------------------
and i need to get all of the same product ID, show their quantity then times that by their price and show the grand total of all.
My problem is i'm trying to show a checkout page which shows everything in a list, but how do i combine the two tables? Also, there are no foreign keys for the first table.
I need this in an sql statement as well preferably, like:
$sql = 'SELECT...'
Would this work?
$sql = "SELECT * FROM order_products
UNION
SELECT * FROM products"
If so, how do i know which row is which?
My desired output is all entries, now looking like this:
ProductID | Quantity | Productname | Desc | Price | Stock | Image
You need a classical JOIN clause:
SELECT *
FROM products
LEFT JOIN order_products on products.ProductId = order_products.ProductId
Not sure exactly what's the output you wish to get is but you should use something like this
SELECT o.ProductID, o.Quantity, p.Price, o.Quantity * p.Price
FROM order_product o
LEFT JOIN products p ON o.ProductID = p.ProductID
My problem is i'm trying to show a checkout page which shows
everything in a list, but how do i combine the two tables?
You need to simply use mysql JOIN to show cart items.
Your table data should be like as i added in demo.
See SQL Fiddle Demo
SELECT
o.id 'orderId',
o.ProductID 'pid',
SUM(o.Quantity) 'qty',
p.productname 'product',
p.`Price` 'price'
FROM
order_product o
INNER JOIN products p
ON p.`ProductID` = o.`ProductID`
Edit Required output
My desired output is all entries, now looking like this:
ProductID | Quantity | Productname | Desc | Price | Stock | Image
Modify above query's SELECT part SELECT tablename.your_column .....
Use inner join.
Select * from order_products op INNER JOIN products p ON p.ProductID = op.ProductID;
w.r.t. your need, the above query needs to be modified to:-
"SELECT *,
SUM(op.quantity * p.price) AS grandTotal
FROM order_products op
INNER JOIN PRODUCT p ON p.ProductID = op.ProductID WHERE p.ProductID =".$prodId(your php variable of product id);
select table1.ProductID
, table1.Quantity
, table2.Productname
, table2.Desc
, table2.Price
, table2.Stock
, table2.Image
FROM table1
JOIN table2 ON table1.productid=table2.productid

Mysql : Products which satisfies category conditions

I want only those products which satisfies following condition :
Which have ((category_id = 1 OR category_id = 2) AND (category_id = 3 OR category_id = 4))
Database structure:
products
id int(10)
name varchar(128)
categories
Id int (10)
name varchar(64)
category_products
product_id int(10)
category_id int(10)
Data:
My product details are:
Products:
id name
1 P1
2 P2
3 P3
4 P4
My category details are:
Categories:
Id name
1 C1
2 C2
3 C3
4 C4
My category-product mapping details are:
category_products:
product_id category_id
1 1
1 3
1 4
2 2
3 1
3 2
3 3
3 4
4 1
4 4
Final Output should be:
id
1
3
4
SELECT DISTINCT p.id, p.name FROM products AS p
INNER JOIN category_products AS c1 ON c1.product_id=p.id
INNER JOIN category_products AS c2 ON c2.product_id=p.id
WHERE c1.category_id IN (1,2) AND c2.category_id IN (3,4)
It wouldn't work to use
WHERE c.category_id IN (1,2) AND c.category_id IN (3,4)
because a WHERE clause tests just one row at a time, and there's no way one category_id can have two values on a single row. So the self-join handles that, by matching more than one row and referencing them by correlation names.
Try this:-
select *
from products
where id in (select distinct(product_id)
from category_products
where (category_id =3 0R category_id=4)
AND (category_id =1 OR category_id=2))
SELECT p.product_id AS id FROM product_categories AS p
WHERE (p.category_id=1 OR p.category_id=2) AND (p.category_id=3 OR p.category_id=4) GROUP BY p.category_id
Because you don't need the name of the product you don't need an INNER JOIN. GROUP BY and DISTINCT should both work.

Complex join query with several joins

I have the following tables
Product
id int(11) AUTO_INCREMENT
name varchar(254)
product_category_id int(11)
A Product belongs to a category in ProductCategories. a category has sub category(self join)
id int(11) AUTO_INCREMENT
name varchar(254)
parent_id int(11)
A Product also has a icon stored in ProductMedia.
id int(11) AUTO_INCREMENT
url varchar(254)
type enum('icon','banner','video')
product_id int(11)
What is the most efficient way to get all products with it's associated icon that belong to a category including products in it's sub category if any.
Example:
Product
1. iphone - Mobile(category)
2. sIII - Mobile (category)
3. liginting connector - Cable(category)
4. iPhone USB charger - Charger(category)
ProductCategories
1. Mobile - 0(parent)
2. Cables - 1(parent)
3. Sim - 1
4. Shoes - 0
5. Chargers - 2
When i search for Mobile Category it needs to give me all 4 products, under cable it needs to give last 2 but under charger only last one
Use joins for this
SELECT
p.*,
pc.name,
pm.url,
pm.type
FROM Product as p
LEFT JOIN ProductMedia as pm ON pm.product_id = p.id
LEFT JOIN ProductCategories as pc ON pc.id = p.product_category_id
You can do it like this
EDITS :
select
p.name,
ifnull(pc.Category,pc.name) as Category,
pm.type
from product as p
left join (select
l.id as id,
l.name,
l.parent_id,
if(r.parent_id <> 0,l.name, CONCAT(l.name,'|',r.name )) as Category
from productcategories as l
left join productcategories as r
on r.id = l.parent_id) as pc
on pc.id = p.id
left join productmedia as pm
on pm.product_id = p.id
Output
name | Category | type
----------------------------------------------------------------
iphone | Mobile | banner
sIII | Charger|Mobile | icon
iphone liginting connector | HeadPhones|Mobile | video
You can explode Category with php explode
According to what i got from you question you want something like this.
SELECT
p.*,
m.url,
m.type
FROM Product as p
LEFT JOIN ProductMedia as m ON m.product_id = p.id
LEFT JOIN ProductCategories as c ON c.id = p.product_category_id
where c.id='Mobile'

Categories