How to combine all these MySQL queries into one? - php

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)";

Related

How to not exist on another table

How to not exist on another table on this two table?
Users table
User_relationships table
and this is my current query
"SELECT * FROM `users`
WHERE CONCAT(first_name, " ", last_name) LIKE '%' . $name . '%'
AND (`role_id` = 6 OR `role_id` = 4)
ORDER BY `first_name` asc limit 15"
and I want to add on query where guardian_id(user_id) not exist on the user_relationships table
UPDATE 1
select * from `users`
where not exists
(select 1 from `user_relationships`
inner join `users` on `user_relationships`.`guardian_id` = `users`.`id`
where `user_relationships`.`student_id` = 422)
I tried this and still returns me zero result.
I only have var name = ? and student_id = ?
try to use "NOT IN" query function with 'DISTINCT'.
following may help you.
select * from users where CONCAT(first_name, " ", last_name) LIKE '%' . $name . '%' and (role_id= 6 or role_id= 4) and (id NOT IN (select DISTINCT guardian_id from User_relationships where student_id = $student_id)) order by first_name ASC limit 15
Let me know if you still need some changes.

Query inside of another query?

I've searched and found ways to do queries inside queries, but I have not found the right answer.
What I am trying to do is to fetch comments from the table called users_profiles_comments and by doing that I will get the field of '.$member["author"].'. Then I want to show who made the comment with their rank and a display picture.
But because there is no user details stored in the comments table because its for comments, I need to create a query inside of my query result where I can have this:
"SELECT * FROM users WHERE username = $member['author'] ORDER BY `id` ASC"
The '.$member["author"].' value comes from the main query but I need it so it can find fields in my users table.
$sql = "SELECT * FROM users_profiles_comments WHERE postid = '1' ORDER BY `id` ASC";
$stm = $dbh->prepare($sql);
$stm->execute();
$users = $stm->fetchAll();
foreach ($users as $row) {
print '
<img src="'.$member["profilepic"].'" style="float:left;margin-right:10px;" width="80px" height="85pxm">
<h4>'. $row["author"] .'
<small>'. $row["date"] .'</small>
</h4>
<p>'. $row["content"] .'</p><hr> </a></li>';
}
echo '
</div>
';
I hope you understand.
Edit:
The database.
users Table
http://img855.imageshack.us/img855/4387/qyjl.png
users_profiles_comments table
http://i.imgur.com/aKRF5MN.png
But because there is no user details stored in the comments table because its for comments
This is good. You do not want to have your database information duplicated in both tables (de-normalized data) - there is no need.
Generally a foreign key is added to inverse side of the relationship. This would mean you have a user_id column within your comments table, allowing you to select the data in one query using a JOIN
SELECT comment.*, user.name AS comment_author
FROM comment
INNER JOIN user ON user.id = comment.user_id
WHERE user.id = 123
Edit - I flipped to JOIN to return comments rather than users, (as you said "to fetch comments") however both ways will work, it just depends which side of the relationship you are on.
Edit 2 To respond to your comment;
How would I be able to show this on my PHP code on the result?
you can be more specific with the above query (not use *) and render it as follows :
$sql = "
SELECT
comment.`date` as comment_date,
comment.content,
user.name AS author_name,
user.profilepic as author_pic
FROM
users_profiles_comments as comment
INNER JOIN
user ON user.id = comment.user_id
WHERE
comment.postid = 1
";
//...
$comments = $stmt->fetchAll();
foreach ($comments as $comment) {
echo '<img src="' . $comment['author_pic'] . '"/>';
echo '<h4>' . $comment['author_name'] . '<small>' . $comment['comment_date'] .'</small></h4>';
echo '<p>' . $comment['content'] . '</p>';
}
You can select member name in SQL statement. You can try this query, this query will bring all the information from two table if users.username = users_profiles_comments.author
WAY 1:
SELECT t1.*, t2.* FROM
(
SELECT * FROM users WHERE username = '.$member["author"].' ORDER BY `id` ASC
) AS t1
LEFT JOIN
(
SELECT * FROM users_profiles_comments WHERE postid = '1' ORDER BY `id` ASC
) AS t2
ON t1.username = t2.author
Finally, do your foreach to print
===================================================================
WAY 2:
You can try this also-
SELECT *,
(SELECT profilepic FROM users WHERE users.username = users_profiles_comments.author) AS profilepic
FROM users_profiles_comments WHERE postid = '1' ORDER BY `id` ASC
And print profilepic using $row['profilepic'] in your foreach loop
=====================================================================
WAY 3:
SELECT t1.*, t2.* FROM
(
SELECT * FROM comments WHERE postid = '1'
) AS t1
LEFT JOIN
(
SELECT * FROM users
) AS t2
ON t1.author = t2.username
What I understand is that you need to get information about the user from another table called user_profile_comments, based on the user id (correct me if wrong: :-)). Use a left outer JOIN to fetch data from another table, limited on user id.
See http://www.w3schools.com/sql/sql_join.asp for more info.

Select row from a table that does not exist in other table

I want to select a row that exist in the images table but not in the images_viewed table. They both share the same name.
This is the code I am using. it works, but it making my website very slow.
$next = $mysqli->query("SELECT `name` FROM `images` WHERE `name` NOT IN (SELECT `name` FROM `images_viewed` WHERE `ip` = '$ip') ORDER BY RAND() LIMIT 1");
if($next->num_rows == 1){
$fetch_next = $next->fetch_assoc();
$next_name = $fetch_next['name'];
}
how can I fix this code? is there a better select statement that I can use?
Try:
SELECT images.name FROM images
LEFT OUTER JOIN images_viewed
ON images.name = images_viewed.name
WHERE images_viewed.ANY_OTHER_FIELD IS NULL AND images_views.ip = {$ip}

Joining two tables to get a count

I am attempting to count comments on a particular page with the following problematic sql query:
$query = "SELECT * FROM `comments` WHERE is_approved = '1' AND page_id = '943'"
$query = mysql_query($query);
$total = mysql_num_rows($query);
echo $total;
the problem is it is outputting 0 and not 2.
The tables are as follows:
pages:
id:1 page_id:943
id:2 page_id:978
id:3 page_id:977
comments:
id:2 page_id:1 "hello"
id:3 page_id:1 "great"
id:4 page_id:3 "super"
So really the original query should be getting each comment's true page_id from the page_id as set in the pages tables, as joined by comments.page_id = pages.id
What would the final code look like to either make that join, and/or get that count? Thank you.
Try:
SELECT c.* FROM `comments` c
JOIN `pages` p on c.page_id = p.id
WHERE c.is_approved = '1' AND p.page_id = '943'
"SELECT * FROM comments, pages WHERE comments.page_id = pages.id AND is_approved = '1' AND comments.page_id = '943'"
Try using:
SELECT count(*) as cnt
FROM `comments` c join pages p on c.page_id = p.id
WHERE c.is_approved = '1' AND p.page_id = '943'
It seems like a very poor database design to have two columns with the same name in different tables that mean different things. You should probably change the name of pages.page_id to something else.
And, this returns the count directly, so you can read the value from the row. If you just want the count, there is no reason to return all the matching rows.
no join is needed:
$query = "SELECT * FROM `comments` WHERE is_approved = '1' AND WHERE page_id IN (SELECT id WHERE page_id = '943')"
$query = mysql_query($query);
$total = mysql_num_rows($query);
echo $total;
ofcourse i would suggest a count statement if you do not need/use the data:
$query = "SELECT COUNT(*) as total FROM `comments` WHERE is_approved = '1' AND WHERE page_id IN (SELECT id WHERE page_id = '943')"
$result = mysql_query($query);
$row = mysql_fetch_assoc($result);
$total = $row['total'];
echo $total;

Help construct a simple query Using 3 tables

Hey guys need some more help
I have 3 tables USERS, PROFILEINTERESTS and INTERESTS
profile interests has the two foreign keys which link users and interests, they are just done by ID.
I have this so far
$statement = "SELECT
InterestID
FROM
`ProfileInterests`
WHERE
userID = '$profile'";
Now I want it so that it selects from Interests where what it gets from that query is the result.
So say that gives out 3 numbers
1
3
4
I want it to search the Interests table where ID is = to those...I just don't know how to physically write it in PHP...
Please help.
Using a JOIN:
Best option if you need values from the PROFILEINTERESTS table.
SELECT DISTINCT i.*
FROM INTERESTS i
JOIN PROFILEINTERESTS pi ON pi.interests_id = i.interests_id
WHERE pi.userid = $profileid
Using EXISTS:
SELECT i.*
FROM INTERESTS i
WHERE EXISTS (SELECT NULL
FROM PROFILEINTERESTS pi
WHERE pi.interests_id = i.interests_id
AND pi.userid = $profileid)
Using IN:
SELECT i.*
FROM INTERESTS i
WHERE i.interests_id IN (SELECT pi.interests_id
FROM PROFILEINTERESTS pi
WHERE pi.userid = $profileid)
You are on the right track, lets say you execute the query above using this PHP code:
$statement = mysql_query("SELECT InterestID FROM `ProfileInterests`
WHERE userID = '$profile'");
Then you can use a PHP loop to dynamically generate an SQL statement that will pull the desired IDs from a second table. So, for example, continuing the code above:
$SQL = "";
while ($statementLoop = mysql_fetch_assoc($statement)) {
//Note the extra space on the end of the query
$SQL .= "`id` = '{$statementLoop['InterestID']}' OR ";
}
//Trim the " OR " off the end of the query
$SQL = rtrim($SQL, " OR ");
//Now run the dynamic SQL, using the query generated above
$query = mysql_query("SELECT * FROM `table2` WHERE {$SQL}")
I haven't tested the code, but it should work. So, this code will generate SQL like this:
SELECT * FROM `table2` WHERE `id` = '1' OR `id` = '3' OR `id` = '4'
Hope that helps,
spryno724
Most likely you want to join the tables
select
i.Name
from
ProfileInterests p
inner join
interests i
on
p.interestid = i.interestid
where
p.userid = 1

Categories