How to delete unknown number last record (on condition)? - mysql

Could you please tell me how to delete unknown number last record (on condition)?
For example, in this situation I want to delete record with id: 6 to 10.
Note: this table and records is not constant.
+----+-----+---------+
| id | url | emailid |
+----+-----+---------+
| 1 | 10 | 1 |
| 2 | 20 | 0 |
| 3 | 30 | 2 |
| 4 | 40 | 0 |
| 5 | 50 | 10 |
| 6 | 60 | 0 |
| 7 | 70 | 0 |
| 8 | 80 | 0 |
| 9 | 90 | 0 |
| 10 | 100 | 0 |
+----+-----+---------+
Thanks...

It seems that you want to delete the last set of records where all the values are 0. This is a bit of a pain. You can find the minimum such id as:
select min(t.id)
from table t
where t.emailid = 0 and
not exists (select 1 from table t2 where t2.id > t.id and t2.emailid <> 0);
The logic is: find all rows where emailid is 0 and there are no subsequent emailids that are not zero.
You can put this into a delete using join:
delete t
from table t cross join
(select min(t.id) as first0id
from table t
where t.emailid = 0 and
not exists (select 1 from table t2 where t2.id > t.id and t2.emailid <> 0)
) tmin
where t.id >= tmin.first0id;

You can use between keyword in your query like this
delete from yourtable where id BETWEEN 6 AND 10

use this query
delete from your_table where id between 6 AND 10
for not being constant you can first store start and end values in variable and then pass in query,example(in php)
$start = 6 ;
$end = 10;
query
"delete from your_table where id between $start AND $end"

Related

How to select rows from two tables using MySQL?

I want to select information from two SQL tables within one query.
table1
id | postID | status | number | userID | active
1 | 1 | 100 | 100 | 3 | 1
2 | 7 | 50 | 25 | 5 | 1
3 | 3 | 75 | 50 | 3 | 1
table2
postID | reference | joint_date | userID | remove
1 | 100 | 100 | 3 | 1
2 | 50 | 25 | 5 | 1
3 | 50 | 50 | 3 | 0
Expected Output
postID | status | number | reference | joint_date
1 | 100 | 100 | 100 | 100
3 | 75 | 50 | 50 | 50
This is my try:
$userID = 12;
$active = 1;
$remove= 1;
$sql = "SELECT table1.status, table1.number, table2.reference, table2.joint_date
FROM table1
WHERE table1.active=:active AND table1.userID=:userID
INNER JOIN table2 ON table1.postID=table2.postID
WHERE table2.postID=:userID
AND table2.remove=:remove
ORDER BY table1.postID DESC";
$stmt = $this->pdo->prepare($sql);
$stmt->bindValue(":active", $active, PDO::PARAM_INT);
$stmt->bindValue(":userID", $userID, PDO::PARAM_INT);
$stmt->bindValue(":remove", $remove, PDO::PARAM_INT);
$stmt->execute();
What is wrong with my query?
What is wrong with my query?
The clauses/statements order are wrong
SELECT....FROM....WHERE....AND....AND....ORDER BY..
You can not have two WHERE condition in the same SELECT (do not take in consideration subqueries)
There is no way you can get the expected result based on the given static variables
Based on the data example you have two condition which will never be true at the same time.
AND t2.postID=3 --- > t2.remove is equal to 0 then you specify
AND t2.remove=1
You can use below example to properly filter based on your conditions:
SELECT t1.postID,
t1.status,
t1.`number`,
t2.reference,
t2.joint_date
FROM table1 t1
INNER JOIN table2 t2 ON t1.postID=t2.postID
WHERE t1.active=1
AND t1.userID=3
ORDER BY t1.postID ASC;
Result:
postID status number reference joint_date
1 100 100 100 100
3 75 50 50 50
Note. I removed both conditions table2.postID=:userID AND table2.remove=:remove
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=78b0f07c7d1dd1db1008e415fc005e85

Select count of rows matching a condition grouped by increments of Id in MySQL

I have a table that has an autoincremented numeric primary. I'm trying to get a count of rows that match a condition grouped by increments of their primary key. Given the data:
| id | value |
|----|-------|
| 1 | a |
| 2 | b |
| 3 | a |
| 4 | a |
| 5 | b |
| 6 | a |
| 7 | b |
| 8 | a |
| 9 | b |
| 10 | b |
| 11 | a |
| 12 | b |
If I wanted to know how many rows matched value = 'a' for every five rows, the result should be:
| count(0) |
|----------|
| 3 |
| 2 |
| 1 |
I can nest a series of subqueries in the SELECT statement, like such:
SELECT (SELECT count(0)
FROM table
WHERE value = 'a'
AND id > 0
AND id <= 5) AS `1-5`,
(SELECT count(0)
FROM table
WHERE value = 'a'
AND id > 5
AND id <=10) AS `6-10`,
...
But is there a way to do this with a GROUP BY statement or something similar where I don't have to manually write out the increments? If not, is there a more time efficient method than a series of subqueries in the SELECT statement as in the above example?
You could divide the ID by 5 and then ceil the result:
SELECT CONCAT((CEIL(id / 5.0) - 1) * 5, '-', CEIL(id / 5.0) * 5), COUNT(*)
FROM mytable
WHERE value = 'a'
GROUP BY CEIL(id / 5.0)
The following aggregated query should do the trick :
SELECT CEIL(id/5), COUNT(*)
FROM table
WHERE value = 'a'
GROUP BY CEIL(id/5)

select count only showing 1 result and the wrong one

I want to search TABLE1 and count which number_id has the most 5's in experience column.
TABLE1
+-------------+------------+
| number_id | experience |
+-------------+------------+
| 20 | 5 |
| 20 | 5 |
| 19 | 1 |
| 18 | 2 |
| 15 | 3 |
| 13 | 1 |
| 10 | 5 |
+-------------+------------+
So in this case it would be number_id=20
Then do an inner join on TABLE2 and map the number that matches the number_id in TABLE1.
TABLE2
+-------------+------------+
| id | number |
+-------------+------------+
| 20 | 000000000 |
| 29 | 012345678 |
| 19 | 123456789 |
| 18 | 223456789 |
| 15 | 345678910 |
| 13 | 123457898 |
| 10 | 545678910 |
+-------------+------------+
So the result would be:
000000000 (2 results of 5)
545678910 (1 result of 5)
So far I have:
SELECT number, experience, number_id, COUNT(*) AS SUM FROM TABLE1
INNER JOIN TABLE2 ON TABLE1.number_id = TABLE2.id
WHERE experience = '5' order by SUM LIMIT 10
But it's returning just
545678910
How can I get it to return both results and by order of number of instances of 5 in the experience column?
Thanks
This query will give you the results that you want. The subquery fetches all the number_id that have experience values of 5. The SUM(experience=5) works because MySQL uses a value of 1 for true and 0 for false. The results of the subquery are then joined to table2 to give the number field. Finally the results are ordered by the number of experience=5:
SELECT t2.number, t1.num_fives
FROM (SELECT number_id, SUM(experience = 5) AS num_fives
FROM table1
WHERE experience = 5
GROUP BY number_id) t1
JOIN table2 t2
ON t2.id = t1.number_id
ORDER BY num_fives DESC
Output:
number num_fives
000000000 2
545678910 1
SQLFiddle Demo
Add a group by clause:
SELECT number, experience, number_id, COUNT(*) AS SUM
FROM TABLE1
JOIN TABLE2 ON TABLE1.number_id = TABLE2.id
WHERE experience = '5'
GROUP BY 1, 2, 3 -- <<< Added this clause
ORDER BY SUM
LIMIT 10

I need to get the average for every 3 records in one table and update column in separate table

Table Mytable1
Id | Actual
1 ! 10020
2 | 12203
3 | 12312
4 | 12453
5 | 13211
6 | 12838
7 | 10l29
Using the following syntax:
SELECT AVG(Actual), CEIL((#rank:=#rank+1)/3) AS rank FROM mytable1 Group BY rank;
Produces the following type of result:
| AVG(Actual) | rank |
+-------------+------+
| 12835.5455 | 1 |
| 12523.1818 | 2 |
| 12343.3636 | 3 |
I would like to take AVG(Actual) column and UPDATE a second existing table Mytable2
Id | Predict |
1 | 11133
2 | 12312
3 | 13221
I would like to get the following where the Actual value matches the ID as RANK
Id | Predict | Actual
1 | 11133 | 12835.5455
2 | 12312 | 12523.1818
3 | 13221 | 12343.3636
IMPORTANT REQUIREMENT
I need to set an offset much like the following syntax:
SELECT #rank := #rank + 1 AS Id , Mytable2.Actual FROM Mytable LIMIT 3 OFFSET 4);
PLEASE NOTE THE AVERAGE NUMBER ARE MADE UP IN EXAMPLES
you can join your existing query in the UPDATE statement
UPDATE Table2 T2
JOIN (
SELECT AVG(Actual) as AverageValue,
CEIL((#rank:=#rank+1)/3) AS rank
FROM Table1, (select #rank:=0) t
Group BY rank )T1
on T2.id = T1.rank
SET Actual = T1.AverageValue

SQL: find based on previous id

I have a table like follows:
mysql> select * from tries;
+----+--------+-----------+
| id | person | succeeded |
+----+--------+-----------+
| 1 | 1 | 1 |
| 2 | 1 | 1 |
| 3 | 2 | 0 |
| 4 | 4 | 1 |
| 5 | 2 | 1 |
| 6 | 2 | 0 |
| 7 | 3 | 0 |
| 8 | 3 | 0 |
| 9 | 3 | 0 |
| 10 | 1 | 0 |
| 11 | 4 | 1 |
| 12 | 4 | 1 |
+----+--------+-----------+
I want the people who had (at least) one try that succeeded, following a try that failed (given by 1 and 0, respectively). When I say "follow", I mean the previous attempt by the same person, given by a lower id.
So in this case:
Person 2 succeeded on id = 5, and failed on id = 3, that person's previous try, thus meets the criteria.
Person 1 has no successes that immediately follow failures, thus fails the criteria
Person 3 has no successes, thus fails the criteria
Person 4 has no failures, thus fails the criteria
How would I write such a query?
SELECT t1.person, MIN(t1.id) as SuccessID
FROM tries t1
WHERE t1.succeeded = 1
AND t1.person IN (SELECT t2.person
FROM tries t2
WHERE t2.succeeded = 0
AND t2.id < t1.id)
GROUP BY t1.person
Select ...
From tries As T
Join tries As T2
On T2.id = T.id + 1
And T2.succeeded = 0
Where T.succeeded = 1
If we cannot assume Ids are perfectly contiguous:
Select ...
From tries As T
Join (
Select T1.id, Min(T2.Id) As NextId
From tries As T1
Join tries As T2
On T2.id > T.id
Group By T1.id
) As TriesAndNext
On TriesAndNext.Id = T.Id
Join tries As TNext
On TNext.Id = TriesAndNext.NextId
And TNext.succeeded = 0
Where T.succeeded = 1