Mysql with GROUP_CONCAT in subselect - mysql

I have problem with subselect in mysql. In table restaurants I have field "sup" where I have IDs separated by comma.
Basic select:
mysql> select name, sup from restaurants LIMIT 5;
+-------------------------------------+---------+
| name | sup |
+-------------------------------------+---------+
| Pizzerija in špagetarija Buf | 2,14,18 |
| EJGA - KAVARNA - RESTAVRACIJA - PUB | 11,17 |
| Restavracija Center | 5,22 |
| Restavracija Viola | 5,13,17 |
| Gostilna Anderlič | 5,17 |
+-------------------------------------+---------+
5 rows in set (0.00 sec)
I want to know the field "SI" from table suply for IDs in sup.restaurants table. So my select for that is:
mysql> SELECT GROUP_CONCAT(suply.SI SEPARATOR ', ') FROM `suply` WHERE id IN (2,14,18);
+---------------------------------------+
| GROUP_CONCAT(suply.SI SEPARATOR ', ') |
+---------------------------------------+
| Italijanska, Špagetarija, Picerija |
+---------------------------------------+
1 row in set (0.00 sec)
So I wrote select with subselct but doesn't work well:
mysql> SELECT restaurants.name,
-> (SELECT GROUP_CONCAT(suply.SI SEPARATOR ', ') FROM `suply` WHERE id IN (restaurants.sup)) AS hrana
-> FROM restaurants
-> LIMIT 5;
+-------------------------------------+--------------------+
| name | hrana |
+-------------------------------------+--------------------+
| Pizzerija in špagetarija Buf | Italijanska |
| EJGA - KAVARNA - RESTAVRACIJA - PUB | Mednarodna kuhinja |
| Restavracija Center | Slovenska domača |
| Restavracija Viola | Slovenska domača |
| Gostilna Anderli? | Slovenska domača |
+-------------------------------------+--------------------+
5 rows in set (0.00 sec)
Why in this select I get just first string?

Use FIND_IN_SET function to search in comma separated list
WHERE FIND_IN_SET(id, restaurants.sup)

Related

Using code to increment values in a column

I am trying to use a simple code to increment only the values in the “chat_id” column of a table.
For the table lz_chat_archive_dup1, the column “chat_id” is has empty strings (no values). This is the partial excerpt of the table :
mysql> select chat_id, fullname from lz_chat_archive_dup1 LIMIT 5;
+---------+--------------+
| chat_id | fullname |
+---------+--------------+
| | Yw |
| | Shah |
| | Sunny Duhel |
| | Leong Zi Yin |
| | Mohd Nasir |
+---------+--------------+
5 rows in set (0.00 sec)
I tried to insert a value for the name “Yw” like this and it worked :
mysql> UPDATE lz_chat_archive_dup1 SET chat_id = '383933' where fullname = 'Yw';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
So now the table is like this :
mysql> select chat_id, fullname from lz_chat_archive_dup1 LIMIT 5;
+---------+--------------+
| chat_id | fullname |
+---------+--------------+
| 383933 | Yw |
| | Shah |
| | Sunny Duhel |
| | Leong Zi Yin |
| | Mohd Nasir |
+---------+--------------+
5 rows in set (0.00 sec)
However, the number of rows in this table is 2589, and for me to do it one by one is tedious and time consuming :
mysql> select count(*) from lz_chat_archive_dup1;
+----------+
| count(*) |
+----------+
| 2589 |
+----------+
1 row in set (0.00 sec)
I thought I could use a code something like this to update/increment only that one column, but I don’t think this is the correct syntax for MySQL. Can you please help to correct the code to customize it to work in my situation :
DECLARE #counter int
SET #counter = 383933
UPDATE #lz_chat_archive_dup1
SET #counter = counter = #counter + 1
So with this code, what I am trying to achieve is increment the chat_id column so that the next value is always 1 integer higher than the previous one. So the first row is 383933, the next one should be 383934, 383935, 383936,…etc etc.
The table has > 2000 rows, so this is an excerpt of it :
mysql> select time, endtime, chat_id from lz_chat_archive_dup1 LIMIT 20;
+------------+------------+---------+
| time | endtime | chat_id |
+------------+------------+---------+
| 1594948770 | 1594948928 | 383933 |
| 1594950285 | 1594950542 | |
| 1594950708 | 1594951085 | |
| 1594953554 | 1594955581 | |
| 1594955956 | 1594956551 | |
| 1595215646 | 1595218410 | |
| 1595215648 | 1595216044 | |
| 1595216110 | 1595216138 | |
| 1595220816 | 1595221144 | |
| 1595221046 | 1595221584 | |
| 1595221448 | 1595221505 | |
| 1595222302 | 1595222653 | |
| 1595236468 | 1595236848 | |
| 1595236954 | 1595237033 | |
| 1595293418 | 1595293589 | |
| 1595303280 | 1595304388 | |
| 1595303410 | 1595303822 | |
| 1595303675 | 1595303986 | |
| 1595304153 | 1595306613 | |
| 1595304878 | 1595304995 | |
+------------+------------+---------+
20 rows in set (0.00 sec)
mysql>
Here is an approach using a user variable:
set #rn = 383933;
update #lz_chat_archive_dup1
set chat_id = (select #rn := #rn + 1)
order by name;
This will assign an incrementingn number to each row, following the alphabetical order of name. If there are ties, it is undefined which name will get which number (a reason why you should have a primary key column in your table).
Assuming the names are unique, you could use a join:
update lz_chat_archive_dup1 cad join
(select cad2.*, row_number() over () as seqnum
from lz_chat_archive_dup1 cad2
) cad2
on cad2.name = cad.name
set count = seqnum + 383933;
I think this might be the recommended approach in MySQL 8+. (The statement on the deprecation of variables is a little vague on whether it would apply to UPDATE.)
You can also use variables. The problem with your statement is:
SET #counter = counter = #counter + 1
This is not even setting the column in the table! It is setting a variable. Use := to set parameters. And I strongly recommend parentheses. So, you can do:
DECLARE #counter int;
SET #counter = 383933;
UPDATE #lz_chat_archive_dup1
SET counter = (#counter := #counter + 1);
Or, in a single statement:
UPDATE #lz_chat_archive_dup1 cad CROSS JOIN
(SELECT #counter := 383933) params
SET cad.counter = (#counter := #counter + 1);
If you can live with numbers starting from 1, following the alphabetic order of your fullname column, you can try with a helper table to run the update:
CREATE TABLE updtab
AS
SELECT
ROW_NUMBER() OVER(ORDER BY fullname) AS chat_id
, fullname
FROM lz_chat_archive_dup1;
Then , run the update:
UPDATE lz_chat_archive_dup1
SET chat_id = (
SELECT chat_id
FROM updtab
WHERE updtab.fullname=lz_chat_archive_dup1.fullname
)
;

mysql query returns empty set when data is there

+----+---------+--------------------+----------+------+---------------------+---------+-------------+------------+----------+
| id | pname | pmail | pgender | page | pdetails | pnumber | ddepartment | date | time |
+----+---------+--------------------+----------+------+---------------------+---------+-------------+------------+----------+
| 1 | karuna | karuna#gmail.com | female | 21 | hfsdh gfhdf shdh | 2332 | Surgeon | 2018-05-15 | 16:00:00 |
+----+---------+--------------------+----------+------+---------------------+---------+-------------+------------+----------+
This is my database table appointment.
Whenever I execute first two queries, they run perfectly
select * from appointment;(execute )
select * from appointment where pname = 'karuna';(execute)
but when I try to execute these two queries, the result I get is empty set
select *from appointment where pmail='karuna#gmail.com';(empty set (0.00 sec))
select *from appointment where ddepartment='Surgeon';(empty set (0.00 sec))

mysql query, different performance between = and IN

why there is this difference of time execution between these two queries even if they retrieve the same amount of rows from the same table?
select cognome, nome, lingua, count(*)
from archivio.utente
where cognome in ('rossi','pecchia','pirono')
group by cognome, nome, lingua;
…
…
…
| Rossi | Mario | it | 1 |
| Pironi | Luigi | it | 1 |
| Pecchia | Fabio | it | 1 |
+----------------------+---------+--------+----------+
779 rows in set (0.03 sec)
select cognome, nome, lingua, count(*)
from archivio.utente
where nome='corrado'
group by cognome, nome, lingua;
…
…
…
| Rossi | Mario | it | 1 |
| Pironi | Luigi | it | 1 |
| Pecchia | Fabio | it | 1 |
+----------------------+---------+--------+----------+
737 rows in set (0.47 sec)
from mysql documentation :
https://dev.mysql.com/doc/refman/5.7/en/explain-output.html#explain-join-types
when we use in
Only rows that are in a given range are retrieved, using an index to select the rows.
The key column in the output row indicates which index is used.
when we use =
A full table scan is done for each combination of rows
So in one case all lines are retrieved and compared, in another case just a range.

MYSQL - Count items separated by comma or not

I have a tinytext field which can contain 3 differents value formatted as followed:
NULL
"X" or "Y" (where X and Y can be any number)
"A,B,C,D" (where A, B, C and D can be any number)
I want to query the table and count the number of items separated or not with a comma.
For example with these lines:
42
NULL
42,56,99
24,10090
Then the expected count would be 6.
I can't find the correct query.
Okay here's the test data:
mysql> create table t (f tinytext);
mysql> insert into t values ('42'), (null), ('42,56,99'), ('24,10090');
mysql> select * from t;
+----------+
| f |
+----------+
| 42 |
| NULL |
| 42,56,99 |
| 24,10090 |
+----------+
You can calculate how many numbers in the string as the difference in the length of the string and the string with commas removed (add 1 for the first number in the list).
mysql> select f, length(f), length(replace(f,',','')), 1+ length(f)-length(replace(f,',','')) from t;
+----------+-----------+---------------------------+----------------------------------------+
| f | length(f) | length(replace(f,',','')) | 1+ length(f)-length(replace(f,',','')) |
+----------+-----------+---------------------------+----------------------------------------+
| 42 | 2 | 2 | 1 |
| NULL | NULL | NULL | NULL |
| 42,56,99 | 8 | 6 | 3 |
| 24,10090 | 8 | 7 | 2 |
+----------+-----------+---------------------------+----------------------------------------+
So then use SUM() to get the total. SUM() ignores NULLs.
mysql> select sum(1+length(f)-length(replace(f,',',''))) from t;
+--------------------------------------------+
| sum(1+length(f)-length(replace(f,',',''))) |
+--------------------------------------------+
| 6 |
+--------------------------------------------+
This would be easier if you don't store comma-separated lists in a string.

INNER JOIN same value, but the difference is the other table are having extra word in front of the value

As I said in the title, or maybe my question is a little bit confusing. Here it is....
So, I want to combine 2 tables using INNER JOIN (ofcourse) with some difference.
This is my tables
Table 1, PK = steam_id
SELECT * FROM nmrihstats ORDER BY points DESC LIMIT 4;
+---------------------+----------------+--------+-------+--------+
| steam_id | name | points | kills | deaths |
+---------------------+----------------+--------+-------+--------+
| STEAM_0:1:88467338 | Alan14 | 50974 | 5438 | 12 |
| STEAM_0:0:95189481 | ? BlacKEaTeR ? | 35085 | 24047 | 316 |
| STEAM_0:1:79891668 | Lowell | 34410 | 44076 | 993 |
| STEAM_0:1:170948255 | Rain | 29780 | 30167 | 278 |
+---------------------+----------------+--------+-------+--------+
4 rows in set (0.01 sec)
Table 2, PK = authid
SELECT * FROM store_players ORDER BY credits DESC LIMIT 4;
+-----+-------------+---------------+---------+--------------+-------------------+
| id | authid | name | credits | date_of_join | date_of_last_join |
+-----+-------------+---------------+---------+--------------+-------------------+
| 309 | 1:88467338 | Alan14 | 15543 | 1475580801 | 1482260232 |
| 368 | 1:79891668 | Lowell | 10855 | 1475603908 | 1482253619 |
| 256 | 1:128211488 | Fuck[U]seLF | 10422 | 1475570061 | 1482316480 |
| 428 | 1:74910707 | Mightybastard | 7137 | 1475672897 | 1482209608 |
+-----+-------------+---------------+---------+--------------+-------------------+
4 rows in set (0.00 sec)
Now, how can I use INNER JOIN without doing like removing "STEAM_0:" or adding it. Also with explanation, please
You can join witn like operator, e.g.:
SELECT n.*, sp.*
FROM nmrihstats n JOIN store_players sp ON n.steam_id LIKE CONCAT('%', sp.authid);
Here's the SQL Fiddle.
Another approach would be to use String functions of MySQL to extract out relevant part from steam_id but I believe that's not what you want:
SELECT SUBSTR(steam_id, LOCATE('STEAM_0:', steam_id) + CHAR_LENGTH('STEAM_0:'))
FROM nmrihstats;
it is not possible, you need to remove "STEAM_0:", matching with WHERE, using substring for remove STEAM_0: from column equals to column in other table, or a new field into the T1 without "STEAM_0:", that 2 columns match for INNER JOIN