Mysql query inside a query - php

First, apologies if the title doesn't match the question. Well, the problem is how to build this query...
I have a table called category It contains categories of my stuff(movies). It's like this...
--------------------------------
ID | name | parent_category
--------------------------------
1 | love | 0
2 | action | 0
3 | fear | 0
4 | passion| 1
5 | danger | 2
6 | death | 3
--------------------------------
So, as you see, each category has a parent category. Except the first 3. They're parents.
And movies table is like this...
--------------------------------
ID | name | category
--------------------------------
1 | aaaa | 1
2 | bbbbbb | 2
3 | cccc | 2
4 | ddddddd| 1
5 | eeeeee | 3
6 | fffff | 3
--------------------------------
So, what i want to do is, to select movies by parent category. Which means if I click category, love, it should select all the movies of categories that having love as the parent category.
So, how to write this in a single query ?

If the parents are only one level deep, then you can use joins:
select m.*,
coalesce(cp.id, c.id) as parent_id,
coalesce(cp.name, c.name) as parent_name
from movies m left join
categories c
on m.category = c.id left join
categories cp
on c.parent_category = cp.id;
Actually, if you only want the id, you don't need two joins:
select m.*,
(case when c.parent_id > 0 then c.parent_id else c.id end) as parent_id
from movies m left join
categories c
on m.category = c.id ;
Or, more simply:
select m.*, greatest(c.parent_id, c.id) as parent_id
. . .

to select rows filtered by condition on secend table use join in FROM clause or subquery in condition with IN or EXISTS function. To compare field with some string you can use LIKE operator.

If you are filtering based on parent_category -
SELECT b.*, a.name FROM movies b
LEFT JOIN categories a ON a.id = b.category
WHERE a.parent_category = 1;

Related

MySQL Join three tables and display 0 if null

I have three tables:
person_table
id| name | gender
1 | Joe | male
2 | Jane |female
3 | Janet | female
4| Jay | male
etc...
product_table
id| name
1 | magazine
2 | book
3 |paper
4 | novel
etc...
**person_product
person_id| product_id | quantity
1 | 1 | 1
1 | 3 | 3
2 | 3 | 1
4 | 4 | 2
etc...
I have tried to make a query that will return a table like this:
person_id| person_name | product_name| quantity
but i can't make it so that if lets say John has no books, it should display
(johns id) John|book|0
instead of just skipping this line.
Where did i go wrong?
here is what i managed to come up with:
SELECT p.*, f.name, l.quantity
FROM person_product AS l
INNER JOIN people_table AS p ON l.person_id=p.id
INNER JOIN product_table AS f ON l.product_id=f.id
ORDER BY id`
It seems that you're generating a report of all people, against all products with the relevant quantity; on a large data set this could take a while as you're not specifically joining product to person for anything other than quantity:
SELECT
p.id,
p.name,
p.gender,
f.name,
IFNULL(l.quantity,0) AS quantity
FROM person_table AS p
JOIN product_table AS f
LEFT JOIN person_product AS l
ON l.person_id = p.id
AND l.product_id = f.id
ORDER BY p.id, f.name
Which results in:
Is that more-or-less what you're after?
you need to start with people_table than using left join you need to bring other table data.
as you need 0 value if null than you can use function IFNULL
SELECT p.*, f.name, IFNULL(l.quantity,0)
FROM people_table AS p
LEFT JOIN person_product AS l ON l.person_id=p.id
LEFT JOIN product_table AS f ON l.product_id=f.id
ORDER BY p.id
if has no book shouldn't appear in the table , try this (easy to understand) :
SELECT NAME
,'0'
,'0'
FROM person_table
WHERE id NOT IN (
SELECT person_id
FROM person_product
)
UNION
SELECT person_id
,product_id
,quantity
FROM person_product;

Mysql IN query instead of multiple AND conditon

I have three mysql tables, category,students and student_category. for each student there is 1 or more category will be there and it is stored in student_category as follows.
1) Categgory
----------------------------
id | category_name
---------------------------
1 | A
2 | B
3 | C
4 | D
2) Students
--------------------------
id | name
--------------------------
1 | John
2 | Kumar
3 | Ashok
4 | Jorge
5 | Suku
-------------------------
2) student_category
-----------------------------------------
id | student_id | category_id
-----------------------------------------
1 | 1 | 2
2 | 1 | 4
3 | 2 | 3
4 | 2 | 1
5 | 3 | 2
------------------------------------------
I need to select students which contain category_id 2 and 4.
i used query as follows but it return either students contain category 2 or category 4.
select A.name from students A, student_category B where A.id=B.student_id
and B.category_id IN (2,4)
Try this query:
SELECT t1.id,
t3.name
FROM students t1
INNER JOIN student_category t2
ON t1.id = t2.student_id
INNER JOIN students t3
ON t1.id = t3.id
WHERE t2.category_id IN (2, 4)
GROUP BY t1.id
HAVING COUNT(DISTINCT t2.category_id) = 2
Explanation:
This query joins together the students and student_category tables, and then removes all records which are not category 2 or 4. This means that each student would then only have category 2 and 4 records associated with him. The HAVING clause then restricts further by requiring that a student have two distinct categories, which if true must mean that the student has both category 2 and 4.
Demo here:
SQLFiddle
try this :
select name from Students where id in (select student_id from student_category where category_id in (2,4))
your query is fine btw.
Try this one:
select
s.name
from
Students s,
Categgory c,
student_category sc
where
sc.student_id = s.id
and sc.category_id = c.id
and c.id = 2
and c.id = 4
You can check it on SQL Fiddle.
Have to take distinct student name as it will repeat if a student falls in more than one category.

How do I select all categories per product and returning this in one row per product?

I'm having a bit of a brain freeze now, because this should be very easy (I think).
I have three tables:
products list
categories list
category_map (links product and category)
I want to list products with its categories (names). One product may have many categories.
// This query
SELECT a.id, a.name, b.category
FROM sl_link_product_category c
LEFT JOIN sl_product a ON c.fk_productID = a.id
LEFT JOIN sl_category b ON c.fk_categoryID = b.id
WHERE c.fk_categoryID = b.id
ORDER BY a.id
// Gives me this result
| 1 | product 1 | cat 1 |
| 1 | product 1 | cat 2 |
| 1 | product 1 | cat 3 |
| 2 | product 2 | cat 2 |
| 2 | product 2 | cat 4 |
Now, in the final result set, I want an array with products where each product has an array of categories.
My question is; Do I have to work with the result set in PHP to achieve my goal? Or is it possible in MySQL to put all categories (comma separated) in one variable / column?
The GROUP_CONCAT function is what you're looking for:
SELECT a.id, a.name, GROUP_CONCAT(b.category)
FROM sl_link_product_category c
LEFT JOIN sl_product a ON c.fk_productID = a.id
LEFT JOIN sl_category b ON c.fk_categoryID = b.id
GROUP BY a.id, a.name
ORDER BY a.id

how to select sum, and count from diffrent tables using multiple joins

I need to generate some big data from many tables, regarding filters, at there also i need to get the sum of some columns, and also counts of rows like example
i have 5 records
ID | NAME | DELETED
1 | A | 1
2 | A | 0
3 | A | 1
4 | B | 1
5 | C | 1
I have the query,
SELECT p.name, sum(p.deleted) as del, count(p.id) as numbers from products as p
join other AS b ON p.id=b.id
The output i need is,
The sum of deleted records
NAME | Deletion | Count
A | 2 | 3
B | 1 | 1
C | 1 | 1
Try this ::
SELECT
p.name,
sum(p.deleted) as del,
count(id) as numbers
from products as p
join other AS b ON p.id=b.id
group by p.name
You should not need to join to get your result. This should work:
SELECT name, sum(deleted), count(1)
FROM products
GROUP BY name
SELECT name,
SUM(CASE WHEN deleted = 1 THEN 1 ELSE 0 END) Deletion,
COUNT(*) `COunt`
FROM products
GROUP BY name
OR
SELECT name,
SUM(deleted) Deletion,
COUNT(*) `COunt`
FROM products
GROUP BY name;
SQLFiddle Demo (both queries)

Multiple count values on one column

I want to query my database and get counts of the occurences of each id in a single column.
The two tables related to this query are:
categories: this table has a list of all categories with titles
id | title
----------
1 | project
2 | tech
3 | other
category_news: this table is used to assign news items to categories, each news item can be in multiple categories
id | category_id | news_id
--------------------------
1 | 1 | 2
2 | 1 | 5
3 | 1 | 3
4 | 2 | 4
5 | 3 | 2
6 | 3 | 1
I would like to get a result of (doesnt have to be an array, I can sort out the results of a query, just using an array below for an example of the returned results):
array(
'project' => 3
'tech' => 1
'other' => 2
);
Where the key is the category title and the value is the total number of news items in each category. I know that I could do it with a query for each category:
select count(cn.category_id), c.title from category_news cn join categories c on c.id = cn.category_id where category_id = 1
But my question is, can I do it with one query to get all the counts? As if I have 100 categories thats 100 queries my way and I would love to do it in one.
Any help would be much appreciated
Regards
Luke
Try this:
SELECT c.title, count(cn.category_id)
FROM categories c
LEFT JOIN categories_news cn
ON c.id = cn.category_id
GROUP BY c.title
This will work(tested):
SELECT COUNT(cn.category_id), c.title
FROM category_news cn
JOIN categories c ON c.id = cn.category_id
GROUP BY cn.category_id
Yes, you can. You have to use a query like the following (tested)
SELECT count( * ) , c.title
FROM category_news cn
JOIN categories c ON c.id = cn.category_id
WHERE 1
GROUP BY cn.category_id

Categories