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
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.
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!
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 |
+-------+-------+----------------------+
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");
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 |
+------+------+------+