problem in php mysql - php

i want to get distinct category name from both photos & videos tables which have category name as in categories table...
here, m trying to execute a mysql query to get distinct categories name from main category table which are coming in both or even in one table i.e. photos & videos...
mysql query:
SELECT DISTINCT t1.category_name FROM categories t1, photos t2, videos t3 WHERE
t1.category_name=t2.category OR t1.category_name=t3.category AND t2.block=0 AND
t3.block=0 ORDER BY t1.category_name asc
here's the structure of all tables...
CATEGORIES:: (MAIN TABLE)
PHOTOS:: (CONTAINS PHOTOS OF ABOVE CATEGORIES)
VIDEOS:: (CONTAINS VIDEOS OF ABOVE CATEGORIES)
please, help me...

I'd use an EXISTS clause
SELECT c.category_name
FROM categories c
WHERE EXISTS (
SELECT 1 FROM photos p
WHERE p.category = c.category_name
UNION
SELECT 1 FROM videos v
WHERE v.category = c.category_name
)

If i understand the question right this would work:
select distinct categories.name
from categories
left join photos on photos.category = categories.name
left join videos on videos.category = categories.name
where (photos.id IS NOT NULL) OR (videos.id IS NOT NULL);
But you should use a foreign key for your connection between category and photo/video.
http://dev.mysql.com/doc/refman/5.1/de/innodb-foreign-key-constraints.html

Change the datatype of photos.category to (INT)
and the videos.category to (INT) it will be way faster when the table become larger
SELECT t1.category_name
FROM categories t1,
JOIN photos p ON p.category = t1.id
JOIN videos v ON v.category = t1.id
GROUP BY t1.category_name
ORDER BY t1.category_name ASC

You need to change the datatype of photos.category to INT instead of varchar and do the same for videos.category, then try below query.
SELECT Cat.category_name
FROM categories As Cat,
JOIN photos AS P ON P.category = cat.id JOIN videos AS vid ON vid.category = Cat.id
GROUP BY Cat.category_name
ORDER BY Cat.category_name ASC
thanks.

Related

relations in SELECT query (PHP)

I have little problem with SQL query in PHP.
I want to get from table post rows with category ex. 'art'.
This table don't contain name of my category (only category_id).
So, how to connect this in my query?
Tables:
post:
id, title, category_id
category:
id, name
I tried this way, but it not works.
SELECT * FROM post WHERE category_id = category.id AND category.name="art";
Anyone can help me? Thanks.
You need to join the tables.
Given your schema, this should give you an starting point:
SELECT p.* FROM post p INNER JOIN category c ON p.category_id = c.id WHERE c.name = 'art';
You are missing the JOIN
SELECT * FROM post
INNER JOIN category
WHERE category_id = category.id AND category.name="art";
You need to use join to query on name column of category table, e.g.:
SELECT p.*
FROM post p JOIN category c ON p.category_id = c.id
WHERE c.name = 'art';

Display categories with number of posts

I'm making a blog. I have 2 tables, one for posts and the other for categories.
I want to display the category name, category date and the number of posts in each category. I have problems to display the number of posts in each category.
In posts table I have a column called cat_id which is equal to category.id
I have these 2 MySQL queries:
mysql_query("select Count(posts.id) as NumberOfPosts, cat_id from posts group by cat_id");
And
mysql_query("select name, date from categories");
I don't know how to have combine these two queries into one query. I'm using PHP.
You could use a join:
SELECT name, date, NumberOfPosts
FROM categories c
JOIN (SELECT cat_id, COUNT(*) AS NumberOfPosts
FROM posts
GROUP BY cat_id) p ON c.id = p.cat_id
EDIT:
To include categories with no posts, you could use a left join instead of regular join. You just need to handle the nulls you'd get for NumberOfPosts, e.g., by using coalesce:
SELECT name, date, COALESCE(NumberOfPosts, 0) AS NumberOfPosts
FROM categories c
LEFT JOIN (SELECT cat_id, COUNT(*) AS NumberOfPosts
FROM posts
GROUP BY cat_id) p ON c.id = p.cat_id

How can i filter my data from mysql?

Let's say i have 3 tables:
table: SONGS
cell: ID primary key
cell: TITLE
cell: ADD_TIME
table: CATEGORIES
cell: ID primary key
cell: title
table: SONGS_CATEGORIES
cell: ID primary key
cell: SONG_ID
cell: CATEGORY_ID
Then let's assume that I have 3 songs(with id's 0, 1, 2), and I have 5 categories(rock, pop, rap and so on) and respectively, their id's(0, 1, 2...). How my sql query should look like, if I want to be able to select more than one category, then I need to look into table SONGS_CATEGORIES and get all songs_id with category id I selected, and then i get songs from table SONGS with those id's?
Hope i explained what i need pretty well, English is not my native language.
If you already know the ID numbers of the categories that you're wanting songs from then the following should do the trick:
SELECT *
FROM SONGS s
JOIN SONGS_CATEGORIES sc
ON s.ID = sc.SONG_ID
WHERE sc.CATEGORY_ID IN (#id1, #id2, #id3...#idN);
If you only know the names of the categories you want the songs for then you can use this:
SELECT *
FROM SONGS s
JOIN SONGS_CATEGORIES sc
ON s.ID = sc.SONG_ID
JOIN CATEGORIES c
ON sc.CATEGORY_ID = c.ID
WHERE c.title IN (#catTitle1, #catTitle2, #catTitle3...#catTitleN);
In both of these examples you would replace the # with the data you are providing and adjust the SELECT part to show only the columns you need.
If you want to select songs from categories 1 & 2 :
SELECT s.id song_id, s.title song_title, s.add_time song_add_time, c.id cat_id, c.title cat_title
FROM CATEGORIES c
INNER JOIN SONGS_CATEGORIES sg
ON c.id = sg.category_id
INNER JOIN SONGS s
ON sg.song_id = s.id
WHERE c.id = 1 OR c.id = 2
I guess this is what you need
SELECT * -- select what ever columns you need to display
FROM SONGS s
JOIN SONGS_CATEGORIES sc
ON s.ID = sc.SONG_ID
JOIN CATEGORIES c
ON c.ID = sc.CATEGORY_ID
where c.title in ('title1','title2')

write mysql query using inner joins for three tables

I have the following query which works perfectly:
SELECT *
FROM contacts
WHERE id in (
SELECT DISTINCT contacts.id
FROM contacts
INNER JOIN contacts2tags
ON contacts.id = contacts2tags.contactid
WHERE tagid in(7,4)
)
Here contacts table contains id, first_name, last_name, ..and tags table contains id, name. contacts2tags table contains contactid and tagid which are same as contacts.id and tags.id respectively
Now, what I want is, to display only the contacts which have both a tagid 7 and a tagid 4.
I tried something like this:
SELECT *
FROM contacts
WHERE id IN
(
SELECT CT1.contactid
FROM
tags T1, contacts2tags CT1, tags T2, contacts2tags CT2
WHERE CT1.contactid = CT2.contactid
AND CT1.tagid = T1.id
AND CT2.tagid = T2.id
AND (T1.id = 7 AND T2.id = 4)
and it works too.
My problem is, I want to convert the above second query to one using inner joins.
I have an array of ids stored in $tmp in php
I want to use those ids and write the above query for them.
How do I do that? I am not comfortable with sql. Might be its a very simple thing to ask.
Thanks in advance
EDIT:
The answer below solved the problem. But the sql runs very slow for 10k records. Any suggestions to optimise it? Pasting the updated query as given in the answer.
SELECT c.id
FROM contacts c
inner join contacts2tags t on c.id = t.contactid
where t.tagid in (7,4)
group by c.id
having count(distinct t.tagid) = 2
This should work
SELECT c.id
FROM contacts c
inner join contacts2tags t on c.id = t.contactid
where t.tagid in (7,4)
group by c.id
having count(distinct t.tagid) = 2

SQL Join question

I have a table vm_category in which I fetch all rows from the category_id and caregory_name columns. I then use this in a drop-down to populate a search-filter module on the left side of the side.
Now doing so gives me a gigantic list of categories, and I'd like to narrow it down by category's sub-category. Those are organized in another table called vm_category_xref in which I have 3 columns;
category_parent_id
category_child_id
category_list
What I'd like to do is specify in my query to only return the category_id and names that match a specific category_parent_id in the _xref table. Here is my current query:
$query = "SELECT `c`.`category_name` AS `name` , `c`.`category_id` AS `id`
FROM `#__vm_category` AS `c` ORDER BY `c`.`category_id`;";
I am not familiar with JOIN enough to figure this out, but I know it should be rather simple, and any help would be much appreciated. Thank you!
Try this:
SELECT
c.category_name AS name,
c.category_id AS id
FROM #__vm_category AS c
INNER JOIN vm_category_xref xr
ON xr.category_child_id = c.category_id
WHERE xr.category_parent_id = 5 /* the parent_id you want to filter on */
ORDER BY c.category_id;
Try this:
SELECT c.category_name as name, c.category_id as id
FROM vm_category as c
INNER JOIN vm_category_xref as x ON
x.category_parent_id = c.category_id
ORDER BY c.category_id
Essentially this returns category_name and category_id only for records that have a category_id that equals a category_parent_id in _xref.
SELECT c.category_name AS name , c.category_id AS id
FROM vm_category c
INNER JOIN vm_category_xref x on c.category_id = x.category_child_id
ORDER BY c.category_id
I may have picked the wrong fields to join on but whichever are the 2 same fields in c and x are the ones you should put in the join condition
select vc.category_id, vc.category_name
from vm_category vc, vm_category_xref vcx
where vc.category_id = vc.category_parent_id
SELECT
c.category_name AS name
,c.category_id AS id
FROM
vm_category AS c
join vm_category_xref vcx
on c.category_id = vcx.category_parent_id
where vcx.category_parent_id = ?
ORDER BY c.category_id;
Replace ? with the id you want to match.
If I'm understanding you correctly, you want to retrieve category_name and category_ID only for certain category parent IDs on the xref.
I typically use IN for situations like these.
I'm assuming that category_id in vm_category maps to category_parent_id in vm_category_xref.
So...
SELECT CATEGORY_NAME, CATEGORY_ID
FROM VM_CATEGORY
WHERE CATEGORY_ID IN
(SELECT CATEGORY_PARENT_ID FROM VM_CATEGORY_XREF
WHERE CATEGORY_PARENT_ID IN ('XXX', 'YYY', 'ZZZ'))
XXX, YYY, ZZZ are the IDs for the categories you want.

Categories