I am unsure how to change a select query to an update.
The select query is:
SELECT IF (strcmp( `player1`, `player2` ) >0, concat(player2, " - ", player1), pair) as GoodPair from scores
The problem I am trying to solve is that the pairs field now contains pair names that are not in the same order. For example "Bill - Dennis" and "Dennis - Bill" for the same pair appear in different records and I want the pair names to be always with the "lesser" name first so that I can count the times that a particular duo is found.
If more info is needed, let me know.
Thanks in advance.
Bili
You can use LEAST and GREATEST functions:
SELECT
CONCAT_WS(' - ', LEAST(payer1,player2), GREATEST(player1,player2)) as GoodPair
FROM
scores
I also prefer to use CONCAT_WS to concatenate strings with a separator instead of CONCAT but in this particular case it is the same.
To create an update query, I would use this:
UPDATE scores
SET
GoodPair = CONCAT_WS(' - ', LEAST(payer1,player2), GREATEST(player1,player2))
If you just need do swith player1 with player2 in case that player1 is greater than player2, you could use this UPDATE query:
UPDATE score
SET player1=LEAST(player1,player2),
player2=GREATEST(player1,player2)
WHERE
player1>player2
Fiddle is here.
Related
I want to count how many columns in a row are not NULL.
The table is quite big (more than 100 columns), therefore I would like to not do it manually or using php (since I dont use php) using this approach Counting how many MySQL fields in a row are filled (or empty).
Is there a simple query I can use in a select like SELECT COUNT(NOT ISNULL(*)) FROM big_table;
Thanks in advance...
Agree with comments above:
There is something wrong in the data since there is a need for such analysis.
You can't completely make it automatic.
But I have a recipe for you for simplifying the process. There are only 2 steps needed to achieve your aim.
Step 0. In the step1 you'll need to get the name of your table schema. Normally, the devs know in what schema does the table reside, but still... Here is how you can find it
select *
from information_schema.tables
where table_name = 'test_table';
Step 1. First of all you need to get the list of columns. Getting just the list of cols won't help you out at all, but this list is all we need to be able to create SELECT statement, right? So, let's make database to prepare select statement for us
select concat('select (length(concat(',
group_concat(concat('ifnull(', column_name, ', ''###'')') separator ','),
')) - length(replace(concat(',
group_concat(concat('ifnull(', column_name, ', ''###'')') separator ','),
'), ''###'', ''''))) / length(''###'')
from test_table')
from information_schema.columns
where table_schema = 'test'
and table_name = 'test_table'
order by table_name,ordinal_position;
Step 3. Execute statement you've got on step 2.
select (length(concat(.. list of cols ..)) -
length(replace(concat(.. list of cols .. ), '###', ''))) / length('###')
from test_table
The select looks tricky but it's simple: first replace all nulls with some symbols that you're sure you'll never get in those columns. I usually do that replacing nulls with "###". that what all that "ifnull"s are here for.
Next, count symbols with "length". In my case it was 14
After that, replace all "###" with blanks and count length again. It's 11 now. For that I was using "length(replace" functions together
Last, just divide (14 - 11) by a length of a replacement string ("###" - 3). You'll get 1. This is exactly amount of nulls in my test string.
Here's a test case you can play with
Do not hesitate to ask if needed
I am trying to replace substrings within one text column in my table using a reference table.
To my knowledge, the replace(column, string1,string2) function will only work with strings as the second and third input.
Here is a visual of what I am trying to do. To be clear, the reference table I need to use is much larger - otherwise, I would use four replace functions.
EDIT: Thank you to everyone who has pointed out how bad this data model is built. Though I am not an expert on building efficient data models, I do know this one is built terribly. However, the structure of this model is completely out of my control. Apologies for not mentioning that from the get-go.
table1
Farms
Animals
Farm1
Cow, Pig
Farm2
Dog, Cow, Cat
Farm3
Dog
referenceTable
refColumn1
refColumn2
Cow
Moo
Pig
Oink
Dog
Bark
Cat
Meow
And here is what I would like the result column to be..
table1
Farms
Animals
Farm1
Moo, Oink
Farm2
Bark, Moo, Meow
Farm3
Bark
First question on stackoverflow so apologies if I missed anything.
Any help is appreciated! Thank you!
To loop over comma (or ', ' in this case) separated values, you can use a double substring_index and a join against a sequence table (where the sequence is <= the number of joined values in a given row, as determined with char_length/replace):
select t1.Farms, group_concat(rt.refColumn2 order by which.n separator ', ') Animals
from table1 t1
join (select 1 n union select 2 union select 3) which
on ((char_length(t1.Animals)-char_length(replace(t1.Animals,', ','')))/char_length(', '))+1 >= which.n
join referenceTable rt on rt.refColumn1=substring_index(substring_index(t1.Animals,', ',which.n),', ',-1)
group by t1.Farms
Here I use an ad hoc sequence table of 1 through 3, assuming no row will have more than 3 animals; expand as necessary or alternatively use a cte.
You have a really lousy data model and you should fix it. You should not be storing multiple values in a string column. Each value pair should be on its own row.
Let me assume that someone else created these tables and you have no choice. If that is the case, MySQL has a solution. I think I would suggest:
select t1.*, -- or whatever columns you want
(select group_concat(rt.refColumn2
order by find_in_set(rt.refColumn1, replace(t1.animals, ', ', ','))
separator ', '
)
from referenceTable rt
where find_in_set(rt.refColumn1, replace(t1.animals, ', ', ',')) > 0
)
from table1 t1
I'm more fluent in Sql Server than MySql, having got a solution working in Sql Server the real challenge was converting to a working MySql version!
See if this meets your needs. It works for your sample data, you may of course need to tweak if it doesn't fully represent your real world data.
with w as (
select *, case when animals like '%' || refcol1 || '%' then locate(refcol1,animals) end pos
from t1
join lateral (select * from t2)t2 on 1=1
)
select farms, group_concat(refcol2 order by pos separator ',') as Animals
from w
where pos>0
group by farms
order by farms
Working DB<>Fiddle
Let's assume I have a table which store register user data, the records might have same registered name but different email, like following:
I want to create a front view to manipulate those data but I don't want those same name show repeatedly, can mysql statement query to output result like
this is the result so far I can do but it can't bind same name into one.
select * from `register`
where `fullname` in (
select `fullname` from `register`
group by `fullname` having count(*) > 1
)
One thing you could do is to do a SELECT DISTINCT on the duplicate row, and make use of the GROUP_CONCAT(); function in MYSQL to concatenate your desired values into one row, and GROUP BY fullname to get the order you wanted.
Note that I am also putting the user ids into a grouped row, so that you can track which ids belong to which name.
SELECT
DISTINCT fullname as full_name,
GROUP_CONCAT(id SEPARATOR ', ') as user_ids,
GROUP_CONCAT(email SEPARATOR ', ') as emails
FROM
tbl_register
GROUP BY
tbl_register.fullname
Working SQL Fiddle
This would be the logical way to do it. Hope this helped. :)
More information on the GROUP_CONCAT(); function here: https://dev.mysql.com/doc/refman/8.0/en/group-by-functions.html#function_group-concat
Try this:
SELECT DISTINCT *duplicate_column* FROM *table_name1* WHERE *col_id* IN (SELECT *cols_to_dusplay* FROM *table_name1* GROUP_BY *duplicate_column*
I am trying to update 1 column with the results of concatenating several rows.
I am able to do it in a Select query but can't figure it out in an Update query.
SELECT GROUP_CONCAT(SizeTemp SEPARATOR ', ') FROM Table GROUP BY ParentSKU
Also, the result separates everything with a coma which is fine but I need the last string NOT to be followed by a coma. In the example below: no coma after XL
S,M,L,XL
Thanks for any help.
You can use update with inner query as shown below:
UPDATE TABLE AS t1,
(SELECT ParentSKU, GROUP_CONCAT(SizeTemp SEPARATOR ', ') AS sizes FROM TABLE GROUP BY ParentSKU) AS t2
SET t1.sizes = t2.sizes
WHERE t1.ParentSKU = t2.ParentSKU
AND t1.ParentSKU = ?
Criteria/column may differ based on which column needs updating.
I'm trying to query the first letter of a last name in MySQL. I want to skip the first name and query the a certain letter in the last name. Thanks
In SKU_data, which SKU has a buyer whose last name begins with 'M'?
*/
select *
from sku_data
where buyer ;
In your where clause, search on WHERE buyer.LastName LIKE 'M%'. This will return all results that start with M.
You need to use a combination of the substring method and the substring_index method in your sql query.
Your select query should look something like this
SELECT SUBSTRING(last_name,1,1)
I'm assuming that your name field has both first and last name in it, instead of separate fields for first and last name. Use the substring_index method to figure out what last_name should be:
SUBSTRING_INDEX(full_name,' ',-1)
Combining this SQL, we have:
SELECT SUBSTRING(SUBSTRING_INDEX(buyer,' ',-1),1,1) as first_letter
Now you can use the first_letter field in a where clause to get your desired result:
SELECT *, SUBSTRING(SUBSTRING_INDEX(buyer,' ',-1),1,1) as first_letter
from sku_data
where first_letter = 'M' ;
Assuming that you have a field like say "full_name" which has first name and last name in the same column.
Lets say the full_name in table employee has a value "JEFF MOSTI"
You can simply use the following statement to get what you need
select * from employee where full_name regexp ' M';
I am assuming you are looking for the last name to start with 'M' and that there is a space (' ') between the first and last name.