UPDATE statement, COUNT with multiple WHERE conditions - mysql

I have TABLE1 as follows
+----------+----------+----------+----------+----------+
+ date + time + course + runner + position +
+----------+----------+----------+----------+----------+
+ 20120701 + 1200 + london + aaa + 1st +
+ 20120701 + 1200 + london + bbb + 2nd +
+ 20120701 + 1200 + london + ccc + 3rd +
+ 20120701 + 1300 + london + eee + 1st +
+ 20120701 + 1300 + london + fff + 2nd +
+ 20120701 + 1400 + new york + ggg + 1st +
+ 20120701 + 1400 + new york + hhh + 2nd +
+ 20120702 + 2000 + london + iii + 1st +
+ 20120702 + 2000 + london + aaa + 2nd +
+ 20120702 + 2100 + new york + iii + 1st +
+ 20120702 + 2100 + new york + bbb + 2nd +
+----------+----------+----------+----------+----------+
and a second table
+------+----------+------+--------+--------+-----+------+-------+
+idtbl2+ date + time + course + runner + pos + link + total +
+------+----------+------+--------+--------+-----+------+-------+
+ 1 + 20120701 + 1200 + london + aaa + 1st + WWW + +
+ 1 + 20120701 + 1200 + london + aaa + 1st + XXX + +
+ 1 + 20120701 + 1200 + london + aaa + 1st + YYY + +
+ 1 + 20120701 + 1200 + london + aaa + 1st + XXX + +
+------+----------+------+--------+--------+-----+------+-------+
Basically I need to count the number of competitors (RUNNER) in a single event from TABLE1 and update that count into the TOTAL field of the second table, TABLE2.
However, TABLE1 is 8500 records in size, and TABLE2 is 65,000 records in size. When running the following query, it timesout and loses the MySQL connection.
update table2 b, table1 a set b.total = (select count(a.runner) from table1 where a.date = b.date AND a.time = b.time AND a.course = b.course AND a.position != 'DQ' );
My limited understanding of JOINs leads me to believe that a JOIN will not help with the efficiency, so I am quite stuck. Any ideas out there?
#MarkByers -
The JOIN creates a temporary table, a concatenation of both table, yes? My thinking is that no matter what, I still have to compare four fields (date, time, course, runner) from one table against another.
I tried this, but it also times out:

Remove table1 from the update clause, as you are already joining the tables (internally) with the nested Select count.... You are joining table2 and table1 without a where clause, the resulting product is so big to be processed that your engine times out.
Check the where clause in the nested select, I think you should filter the query by Runner, otherwise you are counting different Runners that have the same time, date, course, etc; unless that is what you want.
update table2 b
set b.total = (select count(a.runner)
from table1
where a.date = b.date
AND a.time = b.time
AND a.course = b.course
AND a.position != 'DQ'
AND b.runner = a.runner);

Related

how to using group by with condition in mysql

I have some question about how to using group by room_location_id, but when the column room_code is having different value the value is not grouping, so I have some table like this :
+-------+------------------+-----------+
+ id + room_location_id + room_code +
+-------+------------------+-----------+
+ 1 + 1 + 100 +
+-------+------------------+-----------+
+ 2 + 1 + 100 +
+-------+------------------+-----------+
+ 3 + 1 + 100 +
+-------+------------------+-----------+
+ 4 + 2 + 100 +
+-------+------------------+-----------+
+ 5 + 2 + 100 +
+-------+------------------+-----------+
+ 6 + 2 + 100 +
+-------+------------------+-----------+
+ 7 + 1 + 101 +
+-------+------------------+-----------+
+ 8 + 1 + 101 +
+-------+------------------+-----------+
+ 9 + 1 + 101 +
+-------+------------------+-----------+
and for the condition is when room_location_id have the same value with another row value and when is room_code get the same value too, then the id will grouping, but when room_location_id doesn't have the same value with another row and for the room_code too is not having the same value, then the id will make a new row, for the table result is like this :
+-----------+------------------+-----------+
+ id + room_location_id + room_code +
+-----------+------------------+-----------+
+ 1,2,3 + 1 + 100 +
+-----------+------------------+-----------+
+ 4,5,6 + 2 + 100 +
+-----------+------------------+-----------+
+ 7,8,9 + 1 + 101 +
+-----------+------------------+-----------+
Use GROUP_CONCAT:
SELECT GROUP_CONCAT(id) AS id, room_location_id, room_code
FROM yourTable
GROUP BY room_location_id, room_code
ORDER BY room_code, room_location_id;

Mysql Auto increment value in select grouped by Id

I have 3 MySql tables and I need to use some information to populate a new table.
SELECT table1.products_id as 'ID',
concat(table2.table2_name,':',table2.table2_name,':0') as 'att',
concat(table3.table3_name,':',(#cnt := #cnt + 1)) as 'val'
FROM table1, table2, table3
CROSS JOIN (SELECT #cnt := 0) AS dummy
WHERE table1.options_id=table2.table2_id
AND table1.options_values_id=table3.table3_id
AND table2.language_id=4 AND table3.language_id=4
Using this query I obtain all these (correct) informations
+++++++++++++++++++++++++++++++++++++
+ ID + att + val +
+++++++++++++++++++++++++++++++++++++
+ 22 + Taglia:Taglia:0 + S:1 +
+ 22 + Taglia:Taglia:0 + M:2 +
+ 22 + Taglia:Taglia:0 + L:3 +
+ 55 + Taglia:Taglia:0 + S:4 +
+ 55 + Taglia:Taglia:0 + M:5 +
+ 60 + Taglia:Taglia:0 + 1:6 +
+ 60 + Taglia:Taglia:0 + 2:7 +
+ 60 + Taglia:Taglia:0 + 3:8 +
+ 62 + Taglia:Taglia:0 + 8,5:9 +
+++++++++++++++++++++++++++++++++++++
but I need that the autoincrement value restart when ID change, like this:
+++++++++++++++++++++++++++++++++++++
+ ID + att + val +
+++++++++++++++++++++++++++++++++++++
+ 22 + Taglia:Taglia:0 + S:1 +
+ 22 + Taglia:Taglia:0 + M:2 +
+ 22 + Taglia:Taglia:0 + L:3 +
+ 55 + Taglia:Taglia:0 + S:1 +
+ 55 + Taglia:Taglia:0 + M:2 +
+ 60 + Taglia:Taglia:0 + 1:1 +
+ 60 + Taglia:Taglia:0 + 2:2 +
+ 60 + Taglia:Taglia:0 + 3:3 +
+ 62 + Taglia:Taglia:0 + 8,5:1 +
+++++++++++++++++++++++++++++++++++++
How can I do this ?
Partially solved...
#Shadow comment guide me in the right way, but I'm doing something wrong :(
NEW QUERY
SET #num := 0, #type := '';
SELECT *
FROM ( select table1.products_id as id, concat(table2.table2_name,':',table2.table2_name,':0') as 'attributo',concat(table3.table3_name,':',#num) as 'valore' FROM table1, table2, table3
WHERE table1.options_id=table2.table2_id AND table1.options_values_id=table3.table3_id AND table2.language_id=4 AND table3.language_id=4
ORDER BY `table1`.`products_id` ASC) as table_name2
WHERE 0 <= GREATEST(
#num := IF(#type = id, #num + 1, 1),
LEAST(0, LENGTH(#type := id)))
NEW RESULT
+++++++++++++++++++++++++++++++++++++
+ ID + att + val +
+++++++++++++++++++++++++++++++++++++
+ 22 + Taglia:Taglia:0 + S:2 +
+ 22 + Taglia:Taglia:0 + M:4 +
+ 22 + Taglia:Taglia:0 + L:6 +
+ 55 + Taglia:Taglia:0 + S:2 +
+ 55 + Taglia:Taglia:0 + M:4 +
+ 60 + Taglia:Taglia:0 + 1:2 +
+ 60 + Taglia:Taglia:0 + 2:4 +
+ 60 + Taglia:Taglia:0 + 3:6 +
+ 62 + Taglia:Taglia:0 + 8,5:2 +
+++++++++++++++++++++++++++++++++++++
Where I'm wrong?

select not in with multiple fields on same table

I am struggling to build a MySql query to identify missing rows in a table.
The table T structure is the following:
+++++++++++++++++++++++++++++++++++++++++++++++
+ Unique ID + Group + Key1 + Key2 + Value +
+++++++++++++++++++++++++++++++++++++++++++++++
+ 34 + A + d1 + e2 + 123 +
+ 35 + A + d1 + e3 + 456 +
+ 36 + A + d1 + e1 + 444 +
+ 37 + A + d2 + e3 + 555 +
+ 38 + B + d1 + e3 + 555 +
+ 39 + B + d3 + e2 + 111 +
+ ... + ... + ... + ... + ... +
+++++++++++++++++++++++++++++++++++++++++++++++
Rows are grouped with label A and B. I need to identify the set of rows in group A but not in group B by taking Key1 and Key2 into account. Only Unique ID is unique in the table.
In other words, the query should return:
+++++++++++++++++++++++++++++++++++++++++++++++
+ Unique ID + Group + Key1 + Key2 + Value +
+++++++++++++++++++++++++++++++++++++++++++++++
+ 34 + A + d1 + e2 + 123 +
+ 36 + A + d1 + e1 + 444 +
+ 37 + A + d2 + e3 + 555 +
+++++++++++++++++++++++++++++++++++++++++++++++
I would use not exists;
select ta.*
from t ta
where ta.group = 'A' and
not exists (select 1
from t tb
where tb.group = 'B' and tb.key1 = ta.key1 and tb.key2 = ta.key2
);
In MySQL, you can also use multi-column in:
select ta.*
from t ta
where ta.group = 'A' and
(ta.key1, ta.key2) not in (select tb.key1, tb.key2 from t tb where tb.group = 'B');
I prefer not exists simply because many databases don't support multi-column in.

Can I do a mysql command to filter and delete duplicated entry

I have table as linkage with below values
++++++++++++++++++++++++++
+ company_id + industry +
++++++++++++++++++++++++++
+ 1 + a +
+ 1 + b +
+ 2 + a +
+ 2 + c +
+ 3 + a +
+ 4 + c +
+ 5 + a +
++++++++++++++++++++++++++
Is there a way that i can group my industry to get the top count sort by desc order example.
a = count 4
c = count 2
b = count 1
then delete duplicated industry leaving only the industry that has the higher count for each company_id.
Edit 1
This edit is based on OP comment I wish to only have the industry with the highest count, and deleting the rest of the entry for the same company_id. say for company_id 1, we will delete the second row, for company_id 2 we will delete the forth row.
Below is what I have.
++++++++++++++++++++++++++
+ company_id + industry +
++++++++++++++++++++++++++
+ 1 + a +
+ 1 + b +
+ 1 + c +
+ 2 + a +
+ 2 + c +
+ 3 + a +
+ 4 + c +
+ 5 + a +
++++++++++++++++++++++++++
as we see in column industry, a has max count, I would like to keep this entry per duplicated company_id and remove rest all enteries.
Consider company_id=1. I would need to remove second and third row.
Consider company_id=2. I would need to remove fifth row.
For id=3,4,5 nothing will happen as those are not duplicated.
So final data that should be there in my table is
++++++++++++++++++++++++++
+ company_id + industry +
++++++++++++++++++++++++++
+ 1 + a +
+ 2 + a +
+ 3 + a +
+ 4 + c +
+ 5 + a +
++++++++++++++++++++++++++
select t6.company_id,t6.industry from
(select t5.company_id,t5.industry,
row_number() over (partition by t5.company_id order by t5.company_id) rn
from
(select t3.company_id,t4.industry from
(select t2.company_id,max(t2.count) count from(
select m.company_id,m.industry,t1.count from linkage m
join
(select n.industry,count(n.industry) count from linkage n
group by n.industry
order by count desc)t1
on m.industry = t1.industry
order by m.company_id)t2
group by t2.company_id
order by t2.company_id)t3
join
(
select m.company_id,m.industry,t1.count from linkage m
join
(select n.industry,count(n.industry) count from linkage n
group by n.industry
order by count desc)t1
on m.industry = t1.industry
order by m.company_id)t4
on t3.company_id = t4.company_id
and t3.count = t4.count)t5
)t6
where t6.rn = '1'
How about this?
SELECT industry, count(industry) as "total"
FROM linkage
GROUP BY industry
ORDER BY total DESC
Demo at sqlfiddle
Edit 1
Can you take at look at below question.
how can I delete duplicate records from my database
I think that is what you are looking for.
select n.industry,count(n.industry) count from linkage n
group by n.industry
order by count desc
select t3.company_id,t4.industry from
(select t2.company_id,max(t2.count) count from(
select m.company_id,m.industry,t1.count from linkage m
join
(select n.industry,count(n.industry) count from linkage n
group by n.industry
order by count desc)t1
on m.industry = t1.industry
order by m.company_id)t2
group by t2.company_id
order by t2.company_id)t3
join
(
select m.company_id,m.industry,t1.count from linkage m
join
(select n.industry,count(n.industry) count from linkage n
group by n.industry
order by count desc)t1
on m.industry = t1.industry
order by m.company_id)t4
on t3.company_id = t4.company_id
and t3.count = t4.count
Demo at sqlfiddle

Finding two person id which are there in both column

Below is what I have
+++++++++++++++++
+id1 + id2 +
+++++++++++++++++
+ 1 + 2 +
+ 2 + 1 +
+ 1 + 3 +
+ 3 + 2 +
+ 4 + 5 +
+ 5 + 4 +
+++++++++++++++++
What I want to find is the id of two person which are in both column.
Below is what I will have
+++++++++++++++++
+id1 + id2 +
+++++++++++++++++
+ 1 + 2 +
+ 2 + 1 +
+ 4 + 5 +
+ 5 + 4 +
+++++++++++++++++
OR
+++++++++++++++++
+id1 + id2 +
+++++++++++++++++
+ 1 + 2 +
+ 4 + 5 +
+++++++++++++++++
OR
+++++++++++++++++
+id1 + id2 +
+++++++++++++++++
+ 2 + 1 +
+ 5 + 4 +
+++++++++++++++++
Any idea how to achieve this?
Here is testing data
This should get you started:
SELECT
mytable1.id1, mytable1.id2
FROM
myTable mytable1,
myTable mytable2
WHERE
mytable1.id1 = mytable2.id2
AND
mytable2.id1 = mytable1.id2
ORDER BY
mytable1.id1
Demo
The basic id list is this:
select distinct t1.id1
from mytable t1
join mytable t2 on t1.id1 = t2.id2;
If you want rows:
select distinct t1.*
from mytable t1
join mytable t2 on t1.id1 = t2.id2;
If you want any 2 rows:
select distinct t1.*
from mytable t1
join mytable t2 on t1.id1 = t2.id2
limit 2;