How to select rows from two tables using MySQL? - 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

Related

MySQL - How to remove duplicate data entry?

I have below kind of data
id product_id url
10 300 /300/abc
9 300 /300/abc/def
8 200 /200/bcd
7 200 /200/bcd/efg
6 100 /100/cde
5 100 /100/cde/hif
Each rows product_id second value is correct means, id 9,7,5 are correct.
SELECT product_id, COUNT(*) count FROM demo_table GROUP BY product_id HAVING count > 1;
Above query will give me the result which have duplicate values.
How can I delete rest of the records via MySQL query?
Use a self join in the DELETE statement:
DELETE d1
FROM demo_table d1 INNER JOIN demo_table d2
ON d2.product_id = d1.product_id AND d2.id < d1.id;
See the demo.
Results:
| id | product_id | url |
| --- | ---------- | ------------ |
| 9 | 300 | /300/abc/def |
| 7 | 200 | /200/bcd/efg |
| 5 | 100 | /100/cde/hif |

Joining and nesting queries in mysql

Currently, I'm using this nice query:
select
users.name,
sum(race_results.winnings) as total_winnings,
count(CASE WHEN race_results.place=1 THEN 1 ELSE 0 END) AS times_won_first_place
from users
inner join race_results
where race_results.userid = users.id and race_results.place = 1
group by users.id
order by total_winnings desc
to get this
************************************************
| name | total_winnings | times_won_first_place |
| Bob | 4000 | 4 |
| John | 1000 | 1 |
************************************************
the race_results table looks like this
*******************************************
| id | raceid | userid | place | winnings |
| 1 | 1 | 1 | 1 | 1000 |
| 2 | 1 | 2 | 5 | 50 |
| 3 | 1 | 3 | 6 | 50 |
| 4 | 2 | 1 | 1 | 1000 |
| 5 | 2 | 2 | 3 | 250 |
*******************************************
I would like to include four three more columns for something like this
***************************************************************************
| name | total_winnings | total_races | 1st_place | 2nd_place | 3rd_place |
| Bob | 4000 | 5 | 4 | 0 | 0 |
| John | 1000 | 5 | 1 | 1 | 1 |
***************************************************************************
If I were to do separate queries for the new columns, I'd use
select count(raceid) from race_results where userid = 1
select count(raceid) from race_results where userid = 1 and place = 1
select count(raceid) from race_results where userid = 1 and place = 2
select count(raceid) from race_results where userid = 1 and place = 3
to do separate queries would be easy but with the existing query I had to use CASE just to get the count of times a user won 1st place. (using
count(CASE WHEN race_results.place=2 THEN 1 ELSE 0 END)
returns the same results).
How would I nest these or join them into my existing query to get what I want?
You can do it this way:
select
users.name,
sum(race_results.winnings) as total_winnings,
count(*) AS total_races,
sum(race_results.place = 1) AS times_won_first_place ,
sum(race_results.place = 2) AS times_won_second_place,
sum(race_results.place = 3) AS times_won_third_place
from users
inner join race_results
where race_results.userid = users.id
group by users.id
order by total_winnings desc;
With ANSI standard SQL you could use case expressions inside the sum function but since MySQL (and some other databases) evaluate boolean expressions to 1 for true you can replace the case expression with the just the condition to evaluate and then just sum them.
So instead of CASE WHEN race_results.place=1 THEN 1 ELSE 0 END you can do sum(race_results.place=1) and save some space and typing :)
See this SQL Fiddle for an example.

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

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"

MySQL - Get row with the maximum HISTORY ID for COMPONENT IDs in non-existing months

I have a table INVENTORY which consists of inventory items. I have the following table structure:
INSTALLATION_ID
COMPONENT_ID
HISTORY_ID
ON_STOCK
LAST_CHANGE
I need to obtain the row with the max HISTORY ID for records for which the spcified LAST_CHANGE month doesn't exist.
Each COMPONENT_ID and INSTALLATION_ID can occur multiple times, they are distinguished by their respective HISTORY_ID
Example:
I have the following records
COMPONENT_ID | INSTALLATION_ID | HISTORY_ID | LAST_CHANGE
1 | 100 | 1 | 2013-01-02
1 | 100 | 2 | 2013-02-01
1 | 100 | 3 | 2013-04-09
2 | 100 | 1 | 2013-02-22
2 | 100 | 2 | 2013-03-12
2 | 100 | 3 | 2013-07-07
2 | 100 | 4 | 2013-08-11
2 | 100 | 5 | 2013-09-15
2 | 100 | 6 | 2013-09-29
3 | 100 | 1 | 2013-02-14
3 | 100 | 2 | 2013-09-23
4 | 100 | 1 | 2013-04-17
I am now trying to retrieve the rows with the max HISTORY ID for each component but ONLY for COMPONENT_IDs in which the specifiec month does not exists
I have tried the following:
SELECT
INVENTORY.COMPONENT_ID,
INVENTORY.HISTORY_ID
FROM INVENTORY
WHERE INVENTORY.HISTORY_ID = (SELECT
MAX(t2.HISTORY_ID)
FROM INVENTORY t2
WHERE NOT EXISTS
(
SELECT *
FROM INVENTORY t3
WHERE MONTH(t3.LAST_CHANGE) = 9
AND YEAR(t3.LAST_CHANGE)= 2013
AND t3.HISTORY_ID = t2.HISTORY_ID
)
)
AND INVENTORY.INSTALLATION_ID = 200
AND YEAR(INVENTORY.LAST_CHANGE) = 2013
The query seems to have correct syntax but it times out.
In this particular case, i would like to retrieve the maximum HISTORY_ID for all components except for those that have records in September.
Because I need to completely exclude rows by their month, i cannot use NOT IN, since they will just suppress the records for september but the same component could show up with another month.
Could anybody give some pointers? Thanks a lot.
If I understand correctly what you want you can do it like this
SELECT component_id, MAX(history_id) history_id
FROM inventory
WHERE last_change BETWEEN '2013-01-01' AND '2013-12-31'
AND installation_id = 100
GROUP BY component_id
HAVING MAX(MONTH(last_change) = 9) = 0
Output:
| COMPONENT_ID | HISTORY_ID |
|--------------|------------|
| 1 | 3 |
| 4 | 1 |
If you always filter by installation_id and a year of last_change make sure that you have a compound index on (installation_id, last_change)
ALTER TABLE inventory ADD INDEX (installation_id, last_change);
Here is SQLFiddle demo

Remove duplicates from one column keeping whole rows

id | userid | total_points_spent
1 | 1 | 10
2 | 2 | 15
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
With the above table, I would first like to remove duplicates of userid keeping the rows with the largest total_points_spent, like so:
id | userid | total_points_spent
3 | 2 | 50
4 | 3 | 5
5 | 1 | 15
And then I would like to sum the values of total_points_spent, which would be the easy part, resulting in 70.
I am not really sure the "remove" you meant is to delete or to select. Here is the query for select only max totalpointspend record respectively.
SELECT tblA.*
FROM ( SELECT userid, MAX(totalpointspend) AS maxtotal
FROM tblA
GROUP BY userid ) AS dt
INNER JOIN tblA
ON tblA.userid = dt.userid
AND tblA.totalpointspend = dt.maxtotal
ORDER BY tblA.userid