Mysql union exclude duplicate entry by row - php

I have this query:
SELECT * FROM `date1` UNION SELECT * FROM `date2` ORDER BY (count1+count2) DESC
I need exclude duplicate entries by 'ID' column.
Can I do this with UNION?
Update:
table1
+---------+--------+
| id | count1 |
+---------+--------+
| 112337 | 567 |
+----+-------------+
table2
+---------+--------+
| id | count1 |
+---------+--------+
| 112337 | 565 |
+----+-------------+
I want to display only first 'id' data.

You can use NOT EXISTS:
SELECT * FROM date1
UNION
SELECT d2.* FROM date2 d2
WHERE NOT EXISTS (SELECT 1 FROM date1 d1 WHERE d1.id = d2.id)
Also change to UNION ALL, which is more efficient, if you don't want to exclude duplicate rows or if there re no duplicate ids in each table.

Using a union and wrapping it in a main query with aggregation may be what you want.
DROP TABLE IF EXISTS T,T1;
CREATE TABLE T(ID INT, COUNT1 INT);
CREATE TABLE T1(ID INT, COUNT1 INT);
INSERT INTO T VALUES (1,567),(2,20);
INSERT INTO T1 VALUES(1,565),(3,20);
select tid ,
max(case when tcount1 is not null then tcount1 else t1count1 end) cnt
from
(select id tid,count1 tcount1,null t1count1 from t
union
select id tid,null tcount1,count1 from t1
) s
group by tid;
+------+------+
| tid | cnt |
+------+------+
| 1 | 567 |
| 2 | 20 |
| 3 | 20 |
+------+------+
3 rows in set (0.001 sec)

Related

Effective way to update more than 10000 row of data in MYSQL?

I would like to query a table, and update the table data, but the data more than 10000 row, so what is the effective way? My code now:
+----+------+---------+
|id | rank | newrank |
+----------------------+
|1 | 1 | 0 |
|2.. | 2 | 0 |
|10000| 10000| 0 |
+----------------------+
//I am using a template language, DB::query = mysqli_query
$ss = DB::fetch_all("SELECT *FROM t1 ORDER BY rank ASC");
$x = 1;
foreach($ss as $sr){
DB::query("UPDATE t1 SET newrank = '".$x."' WHERE id = '".$sr['id']."'");
$x++;
}
Currently I am using the above code, but if data have to update in huge amount, the server will be crashed. Thank you.
You don't need to fetch anything to do this, and you don't need to worry about the number of rows.*
Given a test table:
create table t1 (id int primary key, `rank` int);
insert into t1 values (1, null), (2, null), (3, null), (6, null);
Solution for MySQL 5.x:
set #r = 0;
update t1 set `rank` = (#r := #r + 1) order by `rank`, id;
select * from t1;
+----+------+
| id | rank |
+----+------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 6 | 4 |
+----+------+
Here's a better solution for MySQL 8.0 using a window function. I'll rank them in the descending order, just so we can see that it changed the ranks:
with cte as ( select id, rank() over (order by `rank` desc, id desc) as r from t1 )
update cte join t1 using (id) set t1.`rank` = cte.r;
select * from t1;
+----+------+
| id | rank |
+----+------+
| 1 | 4 |
| 2 | 3 |
| 3 | 2 |
| 6 | 1 |
+----+------+
Note: I had to delimit rank with back-ticks because rank is a reserved keyword in MSQL 8.0.
* Eventually, you do need to worry about the number of rows. MySQL has a limit on the total size of a transaction, if the binary log is enabled. The total size of rows modified during a transaction is limited by the option max_binlog_cache_size. Not the number of rows, but the size of the rows in bytes.

copying rows in a table into the same table with a different id

Hi I'm trying to copy rows in a table but I need it with a different id, that can be in that table aswell. Both id and second_id are primary key. and foreign keys.
+----+-----------+
| id | second_id |
+----+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 2 |
+----+-----------+
So I need to copy all of second_id of id 1 to the id 2, but and eventually, if there's going to be id 3, copy that aswell.
the result should be
+----+-----------+
| id | second_id |
+----+-----------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 2 | 2 |
| 2 | 1 |
| 2 | 3 |
+----+-----------+
Also id is a foreign key, so if I have id 3 copy it aswell just like id 2
Any solutions ?
Use a self-join of the table to get all the combinations of id and second_id. Then use a LEFT JOIN to filter out the combinations that already exist, so you can insert the rest into the table.
INSERT INTO yourTable (id, second_id)
SELECT DISTINCT t1.id, t2.second_id
FROM yourTable AS t1
CROSS JOIN yourTable AS t2
LEFT JOIN yourTable AS t3 ON t1.id = t3.id AND t2.second_id = t3.second_id
WHERE t3.id IS NULL
DEMO
Instead of the LEFT JOIN you could simply use INSERT IGNORE. Since (id, second_id) is the primary key, the duplicates will simply be ignored when inserting.
INSERT IGNORE INTO yourTable (id, second_id)
SELECT DISTINCT t1.id, t2.second_id
FROM yourTable AS t1
CROSS JOIN yourTable AS t2
DEMO

How to count without duplicates in two columns?

I have table:
+----------------+
| table |
+----------------+
| u_id | sail_id |
+----------------+
| 1 | 5 |
| 1 | 5 |
| 2 | 5 |
| 2 | 4 |
| 1 | 4 |
+----------------+
How to write sql statement to count different u_id with different sail_id (means no duplicate)?
Example:
if SELECT COUNT(*) FROM table GROUP BY sail_id, result will be 2
if SELECT COUNT(*) FROM table GROUP BY sail_id, user_id, result will be 1
I need result to be 4 (because there are 5 rows and only first and second rows have same u_id and sail_id).
Maybe I need add somewhere DISTINCT.
1) You can use COUNT(DISTINCT ...):
SELECT COUNT(DISTINCT u_id,sail_id)
FROM tab;
SqlFiddleDemo
2) You can use subquery with DISTINCT:
SELECT COUNT(*)
FROM (SELECT DISTINCT u_id, sail_id
FROM table) AS sub;
LiveDemo
3) You can use subquery with GROUP BY:
SELECT COUNT(*)
FROM (SELECT u_id, sail_id
FROM table
GROUP BY u_id, sail_id) AS sub;
4) Last possibility is to use:
SELECT COUNT(DISTINCT CONCAT(u_id,',',sail_id))
FROM table;
SqlFiddleDemo

MySQL - Sum values width same ID in same table

I want sum values into my database by the same ID in the same table.
Table in database:
| ID | Value_o | Value_t | Value_tt |
| 1 | 40 | 20 | 10 |
query:
SELECT SUM(Value_o) AS Value_o, SUM(Value_t) AS Value_t, SUM(Value_tt) AS Value_TT
WHERE ID IN(1, 1)
And now the output id:
| Value_o | Value_t | Value_tt |
| 40 | 20 | 10 |
but I want:
| Value_o | Value_t | Value_tt |
| 80 | 40 | 20 |
I want get this output without JOIN.
Thanks!
PS. Sorry for my bad eng :/
Maybe this is what you are looking for:
SELECT
SUM(Value_o) AS Value_o,
SUM(Value_t) AS Value_t,
SUM(Value_tt) AS Value_TT
FROM
(
SELECT ID, Value_o, Value_t, Value_tt FROM Table1
UNION ALL
SELECT ID, Value_o, Value_t, Value_tt FROM Table1
) Table2
WHERE ID IN(1, 1);
Demo
The MySQL in operator doesn't work this way. Even if you have a value multiple times in the set, it doesn't duplicate the rows of your result.
If you want to have all the rows multiple times, you must use union all and sum over that
SELECT SUM(Value_o) AS Value_o, SUM(Value_t) AS Value_t, SUM(Value_tt) AS Value_TT
from (select * from mytable union all select * from mytable) t
WHERE ID IN (1)
Try this:
SELECT SUM(Value_o) AS Value_o, SUM(Value_t) AS Value_t, SUM(Value_tt) AS Value_TT
FROM TABLE
GROUP BY ID
HAVING ID = 1

MYSQL get row rank

I have a mysql table and I need to get random row and get the rank of total view
+--------+------------+---------+
| id | name |totalview|
+--------+------------+---------+
| 1 | ex1 | 20 |
| 2 | ex2 | 100 |
| 3 | ex3 | 30 |
| 4 | ex4 | 40 |
+--------+------------+---------+
for example :
SELECT * FROM `table` WHERE `id` = '$rand';
$rand may be 1 or 2 etc ..
I need to get rank of this row by totalview
thank's
SELECT *,
(SELECT COUNT(*) FROM table t2 WHERE totalview > t1.totalview ) + 1 cnt
FROM table t1
WHERE id = '$rand';
SELECT SUM(ref.totalview < t.totalview) FROM t1 CROSS JOIN t1 ref WHERE t1.id = '$rand'

Categories