Delete query for two way friendship (mysql) - php

Friendship in my DB is a two way street. Check screenshot:
So user id 14 and 1 are friends.
I want a query that can be initiated by either party and that deletes two way street completely removing both rows.
How would I go about doing this? This is not simple WHERE asked asker = id.

Use AND and OR to create a condition from simpler conditions, like
(asker_user_id = 14 AND asked_user_id = 1) OR
(asked_user_id = 14 AND asker_user_id = 1)

DELETE FROM friendship
WHERE (asker_user_id = 14 AND asked_user_id = 1)
OR (asker_user_id = 1 AND asked_user_id = 14)

You could combine 2 IN conditions, to achieve this.
DELETE FROM foo WHERE asker_user_id IN (1, 14) AND asked_user_id IN (1, 14)
http://sqlfiddle.com/#!2/d1866/1

$slq = "SELECT * from Table where `id` = '13' "; //depending on user
$query = mysql_query($sql);
$result = mysql_fetch_array($query);
$asker = $result['asker_user_id']; //14 //
$asked = $result['asked_user_id']; //1
$id = $result['id'];
$del_sql = "DELETE from table WHERE asked_user_id = '.$asker.' AND asker_user_id = '.$asked.'";
$del_query = mysql_query($del_sql);
$del_first = "Delete from table Where `id` = $id";
$del_first_query = mysql_query($del_first);

UPDATED (and tested)
My approach works even if you don't know relationship between 1 and 14. If you are looking for really "(asker = 14 AND asked = 1) OR (asked = 14 AND asker = 1)", it is easy while you are thinking "This is not simple"
Here is what I have tested. I hope this help somebody (including OP). Thanks.
Given Data
CREATE TABLE tab
(
id int,
asker_user_id int,
asked_user_id int
);
insert into tab value(1, 2, 1);
insert into tab value(2, 15, 1);
insert into tab value(3, 14, 1);
insert into tab value(4, 1, 14);
insert into tab value(5, 5, 1);
insert into tab value(6, 1, 5);
insert into tab value(7, 2, 5);
Q1 - find all relationship
SELECT t1.asker_user_id, t1.asked_user_id
FROM tab AS t1 JOIN tab AS t2
WHERE t1.asked_user_id = t2.asker_user_id
AND t2.asked_user_id = t1.asker_user_id
+---------------+---------------+
| asker_user_id | asked_user_id |
+---------------+---------------+
| 1 | 14 |
| 14 | 1 |
| 1 | 5 |
| 5 | 1 |
+---------------+---------------+
Q2 - before delete, check relationship's record id
SELECT DISTINCT A.id as record_id
FROM tab A JOIN
(
// insert Q1 here
) B ON (A.asker_user_id = B.asker_user_id AND A.asked_user_id = B.asked_user_id)
OR (A.asked_user_id = B.asker_user_id AND A.asker_user_id = B.asked_user_id)
+-----------+
| record_id |
+-----------+
| 3 |
| 4 |
| 5 |
| 6 |
+-----------+
Q3 DELETE all friendship record
DELETE A
FROM tab A JOIN
(
// insert Q1 here
) B ON (A.asker_user_id = B.asker_user_id AND A.asked_user_id = B.asked_user_id)
OR (A.asked_user_id = B.asker_user_id AND A.asker_user_id = B.asked_user_id)
Query OK, 4 rows affected (0.00 sec) <== records which has friendship are deleted.
Orig. Answer
Not tested, but I guess it will display both 13 and 14
SELECT *
FROM tab A JOIN
(
SELECT t1.asker_user_id, t2.asked_user_id
FROM tab AS t1 JOIN tab AS t2
WHERE t1.asked_user_id = t2.asker_user_id
AND t2.asked_user_id = t1.asker_user_id
) B ON (A.asker_user_id = B.asker_user_id AND A.asked_user_id = B.asked_user_id)
OR A.asked_user_id = B.asker_user_id AND A.asker_user_id = B.asked_user_id)
when above query works, then delete like this:
DELETE FROM tab
WHERE id IN (
SELECT A.id
FROM tab A JOIN
(
SELECT t1.asker_user_id, t2.asked_user_id
FROM tab AS t1 JOIN tab AS t2
WHERE t1.asked_user_id = t2.asker_user_id
AND t2.asked_user_id = t1.asker_user_id
) B ON (A.asker_user_id = B.asker_user_id AND A.asked_user_id = B.asked_user_id)
OR A.asked_user_id = B.asker_user_id AND A.asker_user_id = B.asked_user_id)
)

Selfjoin:
SELECT *
FROM friendship asker
LEFT JOIN friendship asked
ON asker.asked_user_id = asked.asker_user_id
WHERE asker.asker_user_id IS NOT NULL
I cannot test right now (or just lazy to create an sqlfiddle),
but it is something like this.
I maybe switched asked and asker in a way.
This is the way you can test if you have both (instead of select, use delete, after checking the correct fields)

Related

MySQL SELECT where if condition group

Hi this is what I want to do:
to_id: 5
to_type: 1
from_id: 3
from_type: 2
I want to SELECT ALL WHERE to_id = 5 only if to_type = 1 AND I want to select * where from_id = 3 only if from_type = 2.
how can I do this in a single SELECT statement?
Looks like this is what you want
SELECT * FROM foobar WHERE (to_id = 5 AND to_type = 1) OR (from_id = 3 and from_type = 2)
That is, get all rows that either matches to_id = 5 and to_type = 1, or matches from_id = 3 and from_type = 2.

Select where not exists pdo

I have a query
SELECT *
FROM `user`
WHERE NOT
EXISTS (
SELECT *
FROM roleInEvent
WHERE user.userId = roleInEvent.userId
AND eventId = 1
)
AND user.disciplineId =5
Whenever I run this in my mysql console it returns 1 row. This is correct.
However in my php script it returns zero rows while it is exact the same query.
My php script looks like this:
$db = DatabaseHelper::get();
$st = $db->prepare('SELECT *
FROM `user`
WHERE NOT
EXISTS (
SELECT *
FROM roleInEvent
WHERE user.userId = roleInEvent.userId
AND eventId = 1
)
AND user.disciplineId =5');
$st->execute();
if ($st->errorCode() !== \PDO::ERR_NONE) {
return null;
}
Somebody knows what is the problem here?
The solution was easy.
I forgot to return the results to my javascript
You can use too the IN with a NOT like:
SELECT * FROM user WHERE id_user NOT IN ( SELECT other_data FROM roleInEvent WHERE user.userId = roleInEvent.userId AND eventId = 1 ) AND user.disciplineId =5
If the query: SELECT other_data FROM roleInEvent WHERE user.userId = roleInEvent.userId AND eventId = 1 bring to you something, this result not have to exist in the user table.
Other example is:
Users Table:
---------------------------
id_user | name_user
1 fernando
2 urban
And in other table we have the block users:
Block Users:
id_user_block | id_user | name_user
1 1 fernando
2 2 john lennon
So,i want bring to me only users that not exists in the block users table:
The query will be:
SELECT * FROM Users WHERE id_user NOT IN ( SELECT id_user FROM blocked_users )
So, the last query we are getting:
id_user | name_user
2 john lennon
Greetings!

MySql Tally system with php

I'm trying to condense data that I have in my database into rows with their points tallied to see the most popular.
If I had a data table like:
`data`
item1 item2
1
1 2
1 3
1 3
2 3
And wanted the condensed version to be:
`data_sum`
item1 item2 Tally
1 2 2
1 3 3
2 3 1
How would I achieve this? I have somewhat of an idea here:
$popdata = mysql_query("SELECT * FROM data");
while($add = #mysql_fetch_array($popdata)){
$qitem1 = "SELECT * FROM data_sum WHERE item1='".$add['item1']."'";
$ritem1 = mysql_query($qitem1);
if(mysql_num_rows($ritem1) > 0){
$qitem2 = "SELECT * FROM data_sum WHERE item2='".$add['item2']."'";
$ritem2 = mysql_query($qitem2);
if (mysql_num_rows($ritem2) > 0){
$sql = "UPDATE Tally=Tally + 1 WHERE item1='".$add['item1']."' AND item2='".$add['item2']."'";
$update = mysql_query($sql);
}
else{
$sql = "INSERT INTO data_sum (item1, item2) VALUES('$item1', '$item2')";
$insert = mysql_query($sql);
}
else{
$sql = "INSERT INTO data_sum (item1, item2) VALUES('$item1', '$item2')";
$insert = mysql_query($sql);
}
Yes, I know the total tallies are one more than the rows in the first table. I want the rows with a null column to count towards both tallies with a common factor. This file is going to go through thousands of rows so I want utmost efficiency! Thanks!
All you would need to do is create a new table and then combine an INSERT statement with a GROUP BY'd SELECT statement. This would COUNT() the number of times item1 and item2 were the same and store them in the new tally'd table.
Something along the lines of:
INSERT INTO new_tally_table (item1, item2, Tally)
SELECT item1, item2, COUNT(*)
FROM table
GROUP BY item1, item2
Edit:
Actually re-read the last bit of your question. Think what you want is something like this:
SELECT item1, item2, COUNT(*)
FROM (
SELECT i1.item1, i2.item2
FROM table1 as i1
INNER JOIN (
SELECT DISTINCT item1, item2
FROM table1 WHERE item2 IS NOT NULL
) as i2 ON (i1.item1 = i2.item1)
WHERE i1.item2 IS NULL
UNION ALL
SELECT item1, item2
FROM table1
WHERE item2 IS NOT NULL
) as t
GROUP BY item1, item2
There's probably a better way of writing that though.
There may be a simpler solution, but I can't think of it...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,item1 INT NULL
,item2 INT NULL
);
INSERT INTO my_table (item1,item2) VALUES
(1 ,NULL),
(1 ,2),
(1 ,3),
(1 ,3),
(2 ,3);
SELECT x.item1
, x.item2
, COUNT(DISTINCT y.id)
FROM my_table x
JOIN my_table y
ON y.item1 = x.item1
AND (y.item2 = x.item2 OR y.item2 IS NULL)
AND y.id <= x.id
JOIN
( SELECT item1
, item2
, MAX(id) max_id
FROM my_table
GROUP
BY item1
, item2
) z
ON z.item1 = x.item1
AND z.item2 = x.item2
AND z.max_id = x.id
WHERE x.item2 <> 0
GROUP
BY x.id;
+-------+-------+----------------------+
| item1 | item2 | COUNT(DISTINCT y.id) |
+-------+-------+----------------------+
| 1 | 2 | 2 |
| 1 | 3 | 3 |
| 2 | 3 | 1 |
+-------+-------+----------------------+

PHP/Mysql: 2 selects from same table in one query

This is how my table looks like:
id | name | value
-----------------
1 | user1| 1
2 | user2| 1
3 | user3| 3
4 | user4| 8
5 | user5| 6
6 | user7| 4
7 | user8| 9
8 | user9| 2
What I want to do is to select all the other users, in one query, who's value is user1's value lower than it's value plus 3, higher than it's value minus 3 or equal to it's value.
Something like this:
$result = mysqli_query($con,"SELECT * FROM users WHERE value<'4' OR value>'-2'") or die("Error: ".mysqli_error($con));
while($row = mysqli_fetch_array($result))
{
echo $row['name'].'<br/>';
}
The problem is that users1's value can vary every time the query is run.
Sorry for lame names, but this should work:
NOTE: I named table with your data as "st".
SELECT b.user, a.value as "user1val", b.value as "otheruservalue" FROM st as a
join st as b
on a.user = "user1" and a.user != b.user
where
(b.value > (a.value - 3)) and (b.value < (a.value + 3))
We get unique pairs of user1's value and other user's value by joining same table. After that we just do some simple comparison to filter rows with suitable values.
$user1 = mysql_fetch_assoc(mysql_query("SELECT `value` FROM `users` WHERE id='1'"));
$result = mysql_query("SELECT * FROM `users` WHERE value<'".$user1['value']."+3' OR value>'".$user1['value']."-3'");
Or nested queries :
$result = mysqli_query($con, "select * from `users` where `value` < (select `value` from `users` where `name`='user1')+3 OR `value` > (select `value` from `users` where `name`='user1')-3");

MySql Find multiple rows for each id

I have a table with 3 columns
---QID---TEXT---CID---
I would like to find 20 rows(QID and TEXT) for each distinct CID. I have already prepared string $cid so that I can use WHERE IN statement.
SELECT * FROM questions q1
WHERE cid=(SELECT cid
FROM questions q2
WHERE q2.cid IN ($cids)
GROUP BY q2.cid)
ORDER BY q1.qid LIMIT 20
Thank you!
Simple query:
$query = 'SELECT QID, TEXT FROM yourDb.yourTable WHERE CID = '.$cid;
or, if $cid is an array:
$query = 'SELECT QID, TEXT FROM yourDb.yourTable WHERE CID IN('.implode(',',$cid).')';
To get to the results:
$pdo = new PDO('mysql:host=yourDBServer','login','password');
if (!$stmt = $pdo->query($query))
{
die('query failed');
}
$results = $stmt->fetchAll(PDO::FETCH_ASSOC);
For more info on what you can do with the PDO object, refer to the manual
A quick fix (but not a good one) might be:
$q = 'SELECT QID, TEXT FROM yourDB.yourTB WHERE CID = '.$cid.' LIMIT 20';
In the case of CID IN(1,2,3), I'm not sure if there's a strait forward way of doing this. All I can think of is using unions. Mayby this page can help you out with that.
A fugly fix might also be to ORDER BY CID ASC, and insted of using fetchAll(), do this:
$query = 'SELECT CID,QID, TEXT FROM yourDb.yourTable WHERE CID IN('.implode(',',$cid).')';
//execute query, same as above: $stmt holds results
$results = array();
while($row = $stmt->fetch(PDO::FETCH_ASSOC))
{
if (!is_array($results[$row['CID']))
{
$results[$row['CID']] = array();
}
if (count($results[$row['CID']]) < 20)
{
$results[$row['CID']][] = $row;
}
}
This way, the $results array, will have a key for each CID that was found, and that key's value will be an array of up to 20 records...
The problem is in using the = operator and passing a set of values instead of single one. Change your query to the following and try again
SELECT * FROM questions q1
WHERE cid
IN $cids
ORDER BY q1.qid LIMIT 20
The following snippet uses the MySQL variable trick to assign a number for each row per CID. To keep the example simple I've limited the amount of returned rows to 2 per CID.
select cid
, qid
, text
from (
select if(#last_cid = cid, #rn := #rn + 1, #rn := 1) as rn
, (#last_cid := cid)
, cid
, qid
, text
from YourTable yt
cross join
(select #rn := 0, #last_cid := -1) r
) as SubQueryAlias
where rn < 3;
Data setup:
create table YourTable (QID int, TEXT varchar(50), CID int);
insert YourTable values
(1, 'hi', 1),
(1, 'hi', 1),
(2, 'hi', 1),
(2, 'hi', 1),
(3, 'hi', 2),
(4, 'hi', 2),
(4, 'hi', 2),
(5, 'hi', 3);
This returns up to two rows per CID:
+------+------+------+
| cid | qid | text |
+------+------+------+
| 1 | 1 | hi |
| 1 | 1 | hi |
| 2 | 3 | hi |
| 2 | 4 | hi |
| 3 | 5 | hi |
+------+------+------+

Categories