MYSQL - SELECT AS alias to be used in subquery - mysql

I want to be able to use one of the items I am selecting further down in my sub query.
As you can see in this example I have set the "variable" in question as 100 but in reality this is going to be a dynamic number so I will need to be able to access it in the subquery.
INSERT INTO users_friends (userId, friendId)
SELECT 77, id as noob
FROM users WHERE email = 'a#g.com'
AND
NOT EXISTS (SELECT * FROM users_friends
WHERE userId = 77 and friendId = noob)
LIMIT 1

I'm not completely sure I understand your question, but NOT EXISTS works just like LEFT JOIN and IS NULL. So I think this will work:
SELECT 77, #noob
FROM users u
JOIN (SELECT #noob:= 100) r
LEFT JOIN users_friends uf on u.userid = uf.userid and uf.friendid = #noob
WHERE email = 'a#g.com'
AND uf.userid IS NULL
And here is the SQL Fiddle.

I think the safest approach is to define these in a subquery. I typically give this the alias of const:
INSERT INTO users_friends (userId, friendId)
SELECT const.userId, const.noob
FROM users cross join
(select 77 as userId, 100 as noob) const
WHERE email = 'a#g.com' AND
NOT EXISTS (SELECT *
FROM users_friends
WHERE userId = const.userId and friendId = const.noob
)
LIMIT 1
I am concerned about SGeddes's approach, because it relies on the correct evaluation of variables outside the scope of the query. This might work in this case, but I prefer a solution where the query does not rely on outside variables. By the way, this should also work in any database, and is not MySQL-specific.

EDIT
I would recommend changing your table structure.
CREATE TABLE users_friends(
userid int,
friendid int,
primary key (userid, friendid)
);
CREATE TABLE users (
userid int primary key,
email varchar(100),
name VARCHAR (100),
index (email,name)
);
INSERT INTO users VALUES (1, 'a#g.com', 'noob'), (2,'b#g.com', 'Joe');
INSERT INTO users_friends (userId, friendId)
VALUES (2, (SELECT userId
FROM users
WHERE email = 'a#g.com'
AND name = "noob"
AND NOT exists (SELECT * FROM users_friends as uf
JOIN users as u
ON u.userid = uf.userid
where uf.friendid = 2 AND name = "noob"
)
)
);
SQL FIDDLE DEMO
Try this:
<?php
function select_query ($userid,$friendname, $email){
$host = "host";
$user = "username";
$password = "password";
$database = "database name";
// open connection to databse
$link = mysqli_connect($host, $user, $password, $database);
IF (!$link){
echo ("Unable to connect to database!");
}
ELSE {
//Is someone registered at other conference from table registration
$query = " INSERT INTO users_friends (userId, friendId)
VALUES (".$userId.", (SELECT userId
FROM users
WHERE email = '".$email."'
AND name = '".$friendname."'
AND NOT exists (SELECT * FROM users_friends as uf
JOIN users as u
ON u.userid = uf.userid
where uf.friendid = ".$userId." AND name = '"$friendname"'
)
)
)";
$result = mysqli_query($link, $query);
return $query;
return $result;
}
mysqli_close($link);
}
echo select_query(1,noob,'a#g.com');
?>
Like I mentioned above I not sure what you mean. If you mean dynamic in the sense that you can change the value of the variable this might help. In your previous posts you used PHP. So, my guess is that your are using PHP.

INSERT INTO users_friends (userId, friendId)
SELECT 77, id
FROM users WHERE email = 'a#g.com'
AND
NOT EXISTS (SELECT * FROM users_friends
WHERE userId = 77 and friendId = (SELECT id
FROM users WHERE email = 'a#g.com'))
LIMIT 1

Related

UNION query functionality and the query structure

What I'm trying to achieve is to insert values into a table if that value does not exist in 2 extra tables.
INSERT INTO visitor(
visitor_username,
email,
PASSWORD
)
SELECT * FROM
(
SELECT
'admin2000',
'adminemail#mail.com',
'123456'
) AS tmp
WHERE NOT EXISTS
(
SELECT
admin.admin_username,
admin.email
FROM
admin AS admin
WHERE
admin.admin_username = 'admin2000' AND admin.email =
'adminemail#mail.com'
UNION
SELECT
staff.staff_username,
staff.email
FROM
staff AS staff
WHERE
staff.staff_username = 'admin2000' AND staff.email =
'adminemail#mail.com'
)
LIMIT 1
In the WHERE NOT EXIST part when I only ask for *_username (example: admin_username or staff_username) it works well, but when I need to verify if the email exists too it does not work as intended.
Am I using WHERE NOT EXIST properly? if the username 'admin2000' and email 'adminemail#mail.com' exist on the table 'admin' and I'm trying to insert it into 'visitor' table it inserts it and it should not be doing that.
The problem is the AND in the subqueries. It searches for rows that have that username AND that email. So if you have an admin called admin2000, but with a different e-mail address, that admin won't be returned by the subquery, and so the new row will be inserted.
Use OR instead of AND, and the the problem will be solved.
You seem to want to be writing a query like this:
INSERT INTO visitor (visitor_username, email, PASSWORD)
SELECT t.*
FROM (SELECT 'admin2000' as visitor_username, 'adminemail#mail.com' as email, '123456' as PASSWORD
) t
WHERE NOT EXISTS (SELECT 1
FROM admin a
WHERE a.visitor_username = t.visitor_username AND a.email = t.email
)
UNION
SELECT s.staff_username, s.email, ? as password
FROM staff s
WHERE s.staff_username = 'admin2000' AND s.email =
'adminemail#mail.com';
Note that the second subquery is missing a password, so there is an error.
This seems more concisely written using a single query:
INSERT INTO visitor (visitor_username, email, PASSWORD)
SELECT t.*
FROM (SELECT 'admin2000' as visitor_username, 'adminemail#mail.com' as email, '123456' as PASSWORD
) t
WHERE NOT EXISTS (SELECT 1
FROM admin a
WHERE a.admin_username = t.visitor_username AND a.email = t.email
) AND
NOT EXISTS (SELECT 1
FROM staff s
WHERE s.staff_username = t.visitor_username AND s.email = t.email
);

SQL efficiently select values where that value has a record in another table

There is a table users with fields fbid and fcmtoken. Then there is a table friends with fields fbid and friendfbid. So in friends table, to get all of my friends, it would have to be done like this(just to help you get the idea):
SELECT friendfbid FROM friends WHERE fbid = MYFBID
I need to make a query to get all fcmtokens of my friends. I made it like this and it seems to work:
SELECT
fbid,
fcmtoken
FROM
users
WHERE
EXISTS (
SELECT
friendfbid
FROM
friends
WHERE
fbid = ?
AND friendfbid = users.fbid
)
Is it efficient enough? It seems to create a lot of select queries, so that makes me think about it.
Try moving the WHERE fbid = ? into the outer query:
SELECT
fbid,
fcmtoken
FROM
users
WHERE fbid = ?
AND EXISTS (
SELECT
*
FROM
friends
WHERE
friendfbid = users.fbid
)
But a join might be more efficient:
SELECT
u.fbid,
u.fcmtoken
FROM users AS u
JOIN friends AS f
ON f.friendfbid = u.fbid
WHERE f.friendfbid = ?
SELECT a.friendfbid, b.fcmtoken from friends a, users b where a.fbid = b.fbid

How to correlate data from two separate tables

I am a beginner at SQL. I am trying to write the following statement, but where user is in group (so where group_members.user_id = $_SESSION['user_id']).
SELECT `group_name`, `group_description` FROM `groups`
How do I write this sort of query that relates values from two different tables? Sorry if I haven't explained this well.
EDIT: When I use the query provided by Matthew Haugen, I seem to have the following difficulty: only one set of results is returned in an array.
This is my code for the function that does the query:
function group_summary(){
$sql = secure_mysqli("SELECT `group_name`,`group_description` FROM `groups` WHERE `group_id` IN (SELECT `group_id` FROM `group_members` WHERE `user_id` = ?)", array($_SESSION['user_id']), "i");
$groups = $sql;
return $groups;
}
And this is secure_mysqli:
function secure_mysqli($query, $values, $datatypes) {
global $link;
$stmt = mysqli_prepare($link, $query);
if($stmt !== false){
if(is_array($values)){ foreach ($values as &$value) $ref_values[] = &$value;
call_user_func_array("mysqli_stmt_bind_param", array_merge(array($stmt, $datatypes), $ref_values));
mysqli_stmt_execute($stmt);
return #mysqli_fetch_assoc(mysqli_stmt_get_result($stmt));
}}}
It sounds like you want either this
SELECT * FROM Groups
WHERE Groups.Id IN (SELECT GroupId FROM Group_Members WHERE User_Id = #userid)
Or this
SELECT * FROM Groups
INNER JOIN Group_Members ON Groups.Id = Group_Members.GroupId
WHERE Group_Members = #userid
You will have to perform what is called a JOIN, it depends on what type you want, see here.
So you can do something like the following
SELECT A.GROUP_NAME
, B.GROUP_DESCRIPTION
FROM TABLE1 A
JOIN TABLE2 B
ON A.UNIQUE_KEY = B.UNIQUE_KEY
WHERE GROUP_MEMBERS.USER_ID = $_SESSION['USER_ID']

combing two SELECT statements into a JOIN

I have two tables: table_1: item_id, name ... table_2: image_id, item_id, url
The following function retrieves the 'urls' of the items with the '$name' that is passed in. I first need to get the 'item_id' from table_1 to use in the query. I only need to return the 'url's from table_2.
It currently works fine, but I feel it could be streamlined to be done in one query with a JOIN rather than two separate queries. I've tried using different 'JOIN's to make it work but I can't seem to get it right.
Here's the function as it stands now with the two queries...
function get_items( $name ) {
global $wpdb;
$sql1 = "SELECT `item_id` FROM `table_1` WHERE `name` = '$name'";
$results1 = $wpdb->get_var( $sql1 );
$sql1 = "SELECT `url` FROM `table_2` WHERE `item_id` = '$results1'";
$results2 = $wpdb->get_results( $sql1, ARRAY_A );
return $results2;
}
and here is the 'JOIN' that I tried implementing, but was unsuccessful (I've also switched it around and did a 'LEFT/RIGHT JOIN' as well resulting in the same result) ...
$sql1 = "SELECT `table_2`.`url`
FROM `table_2`
INNER JOIN `table_1`
ON `table_2`.`item_id` = `table_1`.`item_id`
WHERE `table_1`.`item_id` = '$name'";
Any advice on combining these two queries?
The problem with your query is this WHERE table_1.item_id = '$name', it should be the name not the item_id
SELECT b.url
FROM table1 a
INNER JOIN table2 b
ON a.item_id = b.item_id
WHERE a.name = '$name'
select url from table_2 where item_id IN (select item_id from table_1 where name = $name )

How to get 1 row from Table A and multiple rows from Table B

Table A is named "users" and Table B is named "comments". I want to select fields "user_id" and "user_name" from Table A and "date", "comment", "user_id" fields in Table B.
In a nutshell I am trying to get all the users and their comments with 1 query. Can the comments be put in its own array as there will be multiple comments like below or will it just be 1 comment and would have to run 2 queries?
Basic Example
user_id = 1
username = foo
comments[0]['date'] = 1234567890
comments[0]['comment'] = "Hello World!"
comments[1]['date'] = 1234567890
comments[1]['comment'] = "MySQL n00b"
Any basic examples would be great so I can get my head round it.
This would be a general query, to select all the comments of user_id = 1.
SELECT u.user_id, u.user_name, c.`date`, c.`comment`
FROM comments c
INNER JOIN users u ON c.user_id = u.user_id
WHERE c.user_id = 1
Assuming the user_id is 1, here is the code if you want an associative array with all user's comments. There is only one query, using JOIN statement.
$res = mysql_query("SELECT users.user_id as uid, users.user_name as username, comments.date, comments.comment, comments.user_id as cid FROM `users` LEFT JOIN comments on uid=cid WHERE cid = 1");
$i = 0;
while($arr = mysql_fetch_assoc($res))
{
$comments[$i]['date'] = $arr['date'];
$comments[$i]['comment'] = $arr['comment'];
$i++;
}
//var_dump($comments);
We call this JOIN. Better to take some sql/mysql tutorial or you get lost.