Mysql Auto increment value in select grouped by Id - mysql

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?

Related

MySQL: Optimizing queries

How can I write this in a more optimized way?
SELECT week_day
, SUM(min_0 + min_1 + min_2 + min_3)
/ (SELECT SUM(min_0 + min_1 + min_2 + min_3)
FROM Hotel.RegIn) * 100 AS MIN_PERCENTAGE
FROM Hotel.RegIn
WHERE week_day = "Wednesday"
GROUP
BY week_day;
I'd write it as below:
SELECT
"Wednesday",
100 * SUM((week_day = "Wednesday") * (min_0 + min_1 + min_2 + min_3))
/ SUM(min_0 + min_1 + min_2 + min_3) AS MIN_PERCENTAGE
FROM Hotel.RegIn
;
or if you can use multiple statements, another one with easier filters:
SET #var_all_day_total :=
(SELECT SUM(min_0 + min_1 + min_2 + min_3) FROM Hotel.RegIn) / 100;
SELECT
week_day,
SUM(min_0 + min_1 + min_2 + min_3) / #var_all_day_total AS MIN_PERCENTAGE
FROM Hotel.RegIn
-- WHERE week_day = "Wednesday"
GROUP BY
week_day
;
The idea usually is not to redundantly calculate the same values more than once.
You should use derived table in the FROM clause. This way the subquery will be evaluated only once.
SELECT
week_day,
SUM(min_0 + min_1 + min_2 + min_3) / RegInSum.sum_all * 100 AS MIN_PERCENTAGE
FROM
Hotel.RegIn,
(SELECT
SUM(min_0 + min_1 + min_2 + min_3) as sum_all
FROM
Hotel.RegIn) as RegInSum
WHERE week_day = "Wednesday"
GROUP BY week_day;
Note that as far as you restrict your query only to one day of week, you won't get any performance gain by rewriting the query, because the subquery will be evaluated only once in both cases.
See CTE (Common Table Expressions) for more readable syntax of derived tables in newer versions of MySQL.

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;

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.

UPDATE statement, COUNT with multiple WHERE conditions

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);

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;