tags:

views:

217

answers:

2

Here's some background info. I have three MySQL tables (all InnoDB). The first table is used to store images records. The second table is used to store tags (to tag the images with. OMG). The third table is used to store relationships between the images and the tags. Yippee. Here's the structure of the tables.

CREATE TABLE `images` (
  `id` int(8) unsigned NOT NULL AUTO_INCREMENT,
  `image` varchar(32) NOT NULL,
  `type` varchar(10) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB

CREATE TABLE `tags` (
  `id` int(8) unsigned NOT NULL AUTO_INCREMENT,
  `tag` varchar(64) NOT NULL,
  PRIMARY KEY (`id`) 
) ENGINE=InnoDB

CREATE TABLE `images_to_tags` (
  `image_id` int(8) unsigned NOT NULL,
  `tag_id` int(8) unsigned NOT NULL,
  PRIMARY KEY (`image_id`,`tag_id`),
  KEY `tag_id` (`tag_id`),
  CONSTRAINT `images_to_tags_ibfk_2` FOREIGN KEY (`tag_id`) REFERENCES `tags` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `images_to_tags_ibfk_1` FOREIGN KEY (`image_id`) REFERENCES `images` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB

The type field in the images database is either "image/gif", "image/png", or "image/jpeg".

And there you have it. So my tables are happily populated with a quarter million images, 10,000 tags, and a metric shit load of image-tag relationships.

1) I need to be able to count how many images have tags. Currently I am doing so with the following query:

SELECT COUNT(DISTINCT image_id) 
  FROM images_to_tags

Is this the most efficient way to do this? It seems kind of circuitous. Is this the only reasonable query which will achieve this purpose?

2) For each type of image, I want to find out how many images are tagged. So say about 5,000 total images have tags, how would I know how many of those 5,000 tagged images are of type "image/png". This isn't working for me:

SELECT COUNT(id), type 
  FROM images, 
       images_to_tags 
 WHERE images.id = images_to_tags.image_id
A: 

I think you're getting the count of how many images that have tags properly. If you want a count of tags for each image type you should do a count and group by the type. Try this

SELECT count(`id`), `type` FROM `images`, `images_to_tags` WHERE `images`.`id` = `images_to_tags`.`image_id` GROUP BY `images`.`type`
Aaron W.
This counts the total number of tags each images say, organized by type. I was looking for the total number of images that are tagged, organized by type. Sorry for the confusion!
Joel Verhagen
Try making the count similar to your first querySELECT count(DISTINCT `images_to_tags`.`image_id`), `type` FROM `images`, `images_to_tags` WHERE `images`.`id` = `images_to_tags`.`image_id` GROUP BY `images`.`type`
Aaron W.
+1  A: 

A variation on your first query would be:

select count(*) 
from images_to_tags
group by image_id

For your second:

select type, count(*) 
from images 
where id in (select image_id from images_to_tags)
group by type
RedFilter
@mecablaze: I modified my second query after reading your comment to Aaron W.
RedFilter
The first query returns a list of how many occurrences of each tag_id there is.The second query does the same as the other comment (http://stackoverflow.com/questions/1442576/mysql-query-questions-with-a-foreign-key-database/1442619#1442619)
Joel Verhagen
Ah my bad. The second one works perfectly. I will definitely look into the 'in' syntax.
Joel Verhagen
Correct, first one is wrong, it's late :) Nothing wrong with your first query - if speed is a problem make sure image_id is indexed (not sure if making it part of a primary key will cause it to be indexed in MySQL).
RedFilter