简体   繁体   中英

How to combine all these MySQL queries into one?

I have a lot of articles tagged with the tag "dog". I have a new tag now called "cat". I want to add the tag "cat" to all articles that already have the tag "dog". A few articles have both tags. I don't want to retag these with "cats".

In other words, if an article has the tag "dog" and doesn't yet have the tag "cat" I want to add the tag "cat" to it. Here is the script I wrote:

<?php 

    # Get "cat" tag id
    $sql = "SELECT `id`
            FROM tags
            WHERE name = 'cat'
            LIMIT 1";

    $cat_tag = mysql_fetch_assoc(mysql_query($sql));

    # Get "dog" tag id
    $sql = "SELECT `id`
            FROM tags
            WHERE name = 'dog'
            LIMIT 1";

    $dog_tag = mysql_fetch_assoc(mysql_query($sql));

    ######################################

    # Get all nodes tagged with "dog"   
    $sql = "SELECT `node_id`
            FROM node_tags
            WHERE `tag_id` = '" . $dog['id'] . "'";

    $query = mysql_query($sql);
    while($row = mysql_fetch_assoc($query)) {

        # Check to see if current node has "cat" tag already    
        $sql = "SELECT COUNT(*)
                FROM node_tags
                WHERE `node_id` = '" . $row['node_id'] . "'         
                AND `tag_id` = '" . $cat['id'] . "'";


        $check_already_exists = mysql_fetch_assoc(mysql_query($sql));

        # If node doesn't already have "cat" tag, then add it
        if($check_already_exists == '0') {
            $sql = "INSERT INTO `node_tags`(node_id, tag_id) 
                    VALUES('" . $row['node_id'] . "', '" . $cat['id'] . "')";
            mysql_query($sql);
        }
    }

?>

I want to be able to run this directly from my MySQL manager tool. So it can't have any PHP but should be one large SQL query. How to do this?

The following query gets all "dogs" that have no cat id. It then inserts them into the table:

insert into node_tags(node_id, tag_id)
    SELECT id, $cat['id']
    FROM tags t join
         node_tags nt
         on t.node_id = nt.node_id
    WHERE t.name = 'dog'
    group by id
    having max(case when tag_id = $cat['id'] then 1 else 0 end) = 0

You can't do this in one query, because you would need to insert data that depends on selecting data from the same table. The closest you can get is something like this, assuming you have a unique key defined on (node_id,tag_id) :

CREATE TEMPORARY TABLE `tmp` (`node_id` TEXT, `tag_id` TEXT); # Choose better column types if possible
INSERT INTO `tmp` SELECT `node_id`, `tag_id` FROM `node_tags`;
SET @id_cat = (SELECT `id` FROM `tags` WHERE `name`='cat'),
    @id_dog = (SELECT `id` FROM `tags` WHERE `name`='dog');
INSERT IGNORE INTO `node_tags` (`node_id`, `tag_id`)
  SELECT `node_id`, @id_cat FROM `tmp` WHERE `tag_id`=@id_dog
  UNION
  SELECT `node_id`, @id_dog FROM `tmp` WHERE `tag_id`=@id_cat;
DROP TABLE `tmp`;

You can paste this into your MySQL manager tool and it should work.

You can make a insert based in a select clause:

INSERT INTO node_tags (node_id, tag_id)
SELECT node_id, (SELECT MAX(id) FROM tags WHERE name = 'cat') 
FROM node_tags 
WHERE tag_id = (SELECT MAX(id) FORM tags WHERE name = 'dog')

Make a backup before you try something like that ;)

Try this query. I havn't tested this. But I think this will work.

INSERT into node_tags(node_id, tag_id)
( SELECT node_id, tag_id
 FROM node_tags nt , tags t
 where t.id = nt.tag_id AND t.name = 'dog' 
 AND nt.node_id NOT IN (SELECT t1.id FROM node_tags nt1, tags t1
 where nt1.node_id = nt.node_id  AND t1.id = nt1.tag_id AND t1.name = 'cat')
)

First change your table and make (node_id and tag_id) together UNIQUE, because that's what it seems that you need.

ALTER TABLE `node_tags` ADD UNIQUE (`node_id`,`tag_id`);

this is your query:

$sql = "INSERT IGNORE INTO `node_tags`  
        SELECT (SELECT `node_id` FROM node_tags WHERE EXISTS (SELECT tags.* FROM tags WHERE node_tags.`tag_id` = tags.`id` AND tags.name = 'dog') LIMIT 1),
               (SELECT `id` FROM tags WHERE name = 'cat' LIMIT 1)";

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM