MySQL delete based on single criteria - mysql

I'm not sure how to phrase my question and therefore I struggled to find any answer. My data looks something like this:
+------+-------+------------+----+
| id | block | repetition | x |
+------+-------+------------+----+
| 5223 | 1 | 1 | 15 |
| 5223 | 1 | 2 | 17 |
| 5223 | 1 | 3 | 16 |
| 5223 | 2 | 1 | 14 |
| 5223 | 2 | 2 | 15 |
| 6238 | 2 | 1 | 18 |
| 6238 | 2 | 2 | 20 |
| 6238 | 2 | 3 | 20 |
| 6238 | 2 | 4 | 21 |
+------+-------+------------+----+
I would like to query the table to delete the entire block (column) if I detect x < than 15 (just an example). In this example it should delete rows 4 and 5.

delete t1
from your_table t1
inner join
(
select id, block
from your_table
group by id, block
having sum(x < 15) > 0
) t2 on t1.id = t2.id and t1.block = t2.block
You can use a self-join to extract the data you want to delete. When using the same table twice in a query you need to use alias names to distinguish the tables from each other. That is why I used the t1 and t2 alias names.
By joining, the result (that will be deleted) will only be the records that match the inner join.
SQLFiddle demo

Related

How to update a column with the number of rows that have a matching column pair?

I have a table called related_clues which lists the id's of pairs of clues which are related
| id | clue_id | related_clue_id | relatedness |
+----+---------+-----------------+-------------+
| 1 | 1 | 232 | 1 |
| 2 | 1 | 306 | 1 |
| 3 | 1 | 458 | 1 |
| 4 | 2 | 620 | 1 |
| 5 | 2 | 72 | 1 |
| 6 | 3 | 212 | 1 |
| 7 | 3 | 232 | 1 |
| 8 | 3 | 412 | 1 |
| 9 | 3 | 300 | 1 |
+----+---------+-----------------+-------------+
Eventually after a while we may reach two id's such as:
+--------+---------+-----------------+-------------+
| id | clue_id | related_clue_id | relatedness |
+--------+---------+-----------------+-------------+
| 121267 | 1636 | 38 | 1 |
| 121331 | 1636 | 38 | 1 |
+--------+---------+-----------------+-------------+
So in this case, for two distinct id values, we have the same (clue_id, related_clue_id) pair
In this case I would like the relatedness value to be updated to 2, signalling that there are two examples of this (clue_id, related_clue_id) pair. Like so:
+--------+---------+-----------------+-------------+
| id | clue_id | related_clue_id | relatedness |
+--------+---------+-----------------+-------------+
| 121267 | 1636 | 38 | 2 |
| 121331 | 1636 | 38 | 2 |
+--------+---------+-----------------+-------------+
So essentially I would like to run some SQL that sets the relatedness value to the number of times a (clue_id, related_clue_id) pair appears.
When I have no relatedness column present, and I simply run the SQL:
SELECT id, clue_id, related_clue_id, COUNT(*) AS relatedness
FROM `related_clues`
GROUP BY clue_id, related_clue_id
It gives me the required result, but of course this doesn't store the relatedness column, it simply shows the column if I run this select. So how do I permanently have this relatedness column?
You could use a update with join
Update related_clues a
INNER JOIN (
SELECT clue_id, related_clue_id, COUNT(*) AS relatedness
FROM `related_clues`
group by clue_id, related_clue_id
having count(*) = 2
) t on t.clue_id = a.clue_id
and t.related_clue_id = a.related_clue_id
set a.relatedness = t.relatedness
I would approach this as an update/join but filter out rows that don't need to be updated:
update related_clues rc join
(select clue_id, related_clue_id, COUNT(*) AS cnt
from `related_clues`
group by clue_id, related_clue_id
) t
on t.clue_id = rc.clue_id and
t.related_clue_id = rc.related_clue_id
set rc.relatedness = t.relatedness
where rc.relatedness <> t.relatedness;

Merge 2 different mysql tables

I have two tables:
Table a:
+----+------+
| id | data |
+----+------+
| 1 | 450 |
| 2 | 500 |
| 3 | 550 |
| 4 | 600 |
| 5 | 650 |
+----+------+
Table b:
+----+------+------+
| id | a_id | note |
+----+------+------+
| 1 | 2 | 25 |
| 2 | 5 | 10 |
+----+------+------+
I need a query that returns a table that consists of every row from table a with the notes from table b. I want 0 filled in where a note isn't available on a row. I want it to look like this:
+----+------+------+
| id | data | note |
+----+------+------+
| 1 | 450 | 0 |
| 2 | 500 | 25 |
| 3 | 550 | 0 |
| 4 | 600 | 0 |
| 5 | 650 | 10 |
+----+------+------+
How do I do that?
select a.id, a.data, coalesce(b.note, 0) as note
from a
left join b on a.id = b.a_id
What are you looking for is called LEFT/RIGHT JOIN. This question will give you more details about what they are.
Assume you have a query like:
SELECT * FROM a LEFT JOIN b ON some_condition;
Then, its output will contain every row from table a, along with data from table b where the condition is met. For rows where the condition is not met, the columns with data from b will contain null.

How to create a simple crosstab query in MySQL

I have two tables containing fields as below.
Table 1
| SetID | InQty | Day |
| 1 | 10 | 1 |
| 2 | 10 | 2 |
| 3 | 10 | 3 |
Table 2
| SetID | OtQty | Day |
| 1 | 1 | 5 |
| 1 | 2 | 6 |
| 1 | 3 | 7 |
SetID in table 2 is linked with SetId in table 1. Day is placed in place of date, just for convenience only. Expected Output,
| Day | InQty | OtQty |
| 1 | 10 | |
| 5 | | 1 |
| 6 | | 2 |
| 7 | | 3 |
Blank Space can be filled with NULL or Zero.
It appears you are querying ONLY for set ID = 1 otherwise, I would expect to see in/out values for Set 2 and 3. You should be able to get with a simple UNION
select t1.Day, t1.InQty, 0 OutQty
from Table1 t1
where SetID = 1
order by t1.Day
union select t2.Day, 0, t2.OtQty
from Table2 t2
where SetID = 1
Now, if you want totals spanning different "setID"s and keeping them differentiated from each other, just add the setID as a column and also add to the group by clause as well.

How to fetch data from two tables using mysql query with some conditions applied to the second table?

I want to generate a result from a MySql query with below requirement.
Table 1 :
---------------
| nid | type |
---------------
| 1 | forum |
| 2 | forum |
| 3 | forum |
| 4 | forum |
---------------
Table 2
-----------------------
| nid | cid | created |
-----------------------
| 1 | 32 | 123456 |
| 2 | 65 | 123457 |
| 4 | 67 | 123458 |
| 1 | 61 | 123491 |
| 1 | 78 | 123497 |
| 2 | 23 | 123498 |
| 1 | 12 | 123698 |
| 4 | 54 | 132365 |
| 4 | 81 | 135698 |
| 1 | 30 | 168965 |
-----------------------
Now i require result like below. (Condition : I need the nid from first table, smallest cid for the corresponding nid in second table WHERE type = 'forum')
--------------
| nid | cid |
--------------
| 1 | 12 |
| 2 | 23 |
| 4 | 67 |
--------------
You can try this
SELECT tbl1.nid,
min(tbl2.cid) as cid
FROM table1 tbl1
INNER JOIN table2 tbl2 ON tbl1.nid=tbl2.nid
GROUP BY tbl2.nid;
SQL Fiddle
Try this
SELECT t1.nid,
min(t2.cid) as cid
FROM table1 t1
INNER JOIN table2 t2 ON t1.nid=t2.nid
GROUP BY t2.nid;
This could also work
select nid, min(cid) cid
from table2
group by nid
The above queries are have issues in group by clause. Kindly check this query.
SELECT t1.NID, MIN(t2.CID) AS cis from
TAB1 t1 inner join TAB2 t2 on t1.nid = t2.nid
group by t1.nid

Select Distinct Set Common to Subset From Join Table

Given a join table for m-2-m relationship between booth and user
+-----------+------------------+
| booth_id | user_id |
+-----------+------------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 5 |
| 1 | 9 |
| 2 | 1 |
| 2 | 2 |
| 2 | 5 |
| 2 | 10 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 4 |
| 3 | 6 |
| 3 | 11 |
+-----------+------------------+
How can I get a distinct set of booth records that are common between a subset of user ids? For example, if I am given user_id values of 1,2,3, I expect the result set to include only booth with id 3 since it is the only common booth in the join table above between all user_id's provided.
I'm hoping I'm missing a keyword in MySQL to accompish this. The furthest I've come so far is using ... user_id = all (1,2,3) but this is always returning an empty result set (I believe I understand why it is though).
The SQL query for this will be:
select booth_id from table1 where [user_id]
in (1,2,3) group by booth_id having count(booth_id) =
(select count(distinct([user_id])) from table1 where [user_id] in (1,2,3))
If this could help you creating the MySQL query.