How to compare values of text columns from the same table - mysql

I have a table in which each column represent a text from a manuscript, here is a simple example:
mss1 | mss2 | mss3
------------------------
The | The | A
big | big | big
black | |
dog | dog | dog
I would like to display rows where two columns have different values (or the same values), for instance I want to see the differences between mss1 and mss3. The result should look like:
mss1 | mss3
---------------
The | A
black |
These seemed to be good solution candidates :
SELECT mss1, mss3 FROM table WHERE mss1 != mss3;
SELECT mss1, mss3 FROM table WHERE mss1 NOT LIKE mss3;
However it is not working, even after converting all columns from text to varchar of the same length.
I also tried LOCATE (See here) to find same values: if I can locate mss1 in mss3 and vice-versa, they must have the same value, right? But that was not successful either.
Any idea? It seems like it should be easy, but I can't figure it out...

Perhaps the issue with your query is that NULL values are filtered out. For your purposes, I think this may do what you want:
SELECT mss1, mss3
FROM table
WHERE coalesce(mss1, '') <> coalesce(mss3, '');

Related

MySql Regexp result word part of known word

Been struggling for this for awhile.
Is there a way to find all rows in my table where the word in the column 'word' is a part of a search word?
+---------+-----------------+
| id_word | word |
+---------+-----------------+
| 177041 | utvälj |
| 119270 | fonders |
| 39968 | flamländarens |
| 63567 | hänvisningarnas |
| 61244 | hovdansers |
+---------+-----------------+
I want to extract the row 119270, fonders. I want to do this by passing in the word 'plafonders'.
SELECT * FROM words WHERE word REGEXP 'plafonders$'
That query will of course not work in this case, would've been perfect if it had been the other way around.
Does anyone know a solution to this?
SELECT * FROM words WHERE 'plafonders' REGEXP concat(word, '$')
should accomplish what you want. Your regex:
plafonders$
is looking for plafonders at the end of the column. This is looking for everything the column has until its end, e.g. the regexp is fonders$ for 119270.
See https://regex101.com/r/Ytb3kg/1/ compared to https://regex101.com/r/Ytb3kg/2/.
MySQL's REGEXP does not handle accented letters very well. Perhaps it will work OK in your limited situation.
Here's a slightly faster approach (though it still requires a table scan):
SELECT * FROM words
WHERE 'PLAutvälj' =
RIGHT('PLAutvälj', CHAR_LENGTH(word)) = word;
(To check the accents, I picked a different word from your table.)

Output data from a MySQL table one time with php

I have a mysql table with a column that looks something like this:
| TAGS |
------
|Green |
|Blue |
|Orange|
|Blue |
|Green |
| ... |
------
Now what I want to do is output all the different tags that exist in a list, BUT every tag can only be outputted once (so e.g. 'Green stands two times in the database but can only stands one time in the list')
Hope you understand my question!
Thanks
You said "row" but do you mean a column labeled "tags" in your table?
There are two different ways:
Method 1:
SELECT DISTINCT tags FROM table_name WHERE condition;
Method 2:
SELECT tags FROM table_name WHERE condition GROUP BY tags;
They both will return a you an array where each item in the row is the tag without repeats (distinct). The main difference is that DISTINCT makes it easier to optimize (and possibly quicker).
Now, if you didn't make a typo and said that you have a row with a column that has multiple tags like:
|ROW_ID|TAGS |
| 1 |'Blue', 'Red' |
| 2 |'Red', 'Yellow' |
| 3 |'Blue', 'Black', 'Red'|
Then you'll have to do some parsing and array operations (but that's a completely different answer).

SELECTing (almost) duplicate rows

My table looks something like this:
| id (int) | sentence (varchar) |
I want to find all rows that are almost the same except for one particular word. Eg:
| 230 | test |
| 321 | test sth |
...
| 329 | is (sth) it?
| 923 | is it?
The word that can be different is sth in this case. Ideally I could use some sort of "array" with the list of words that can be different.
Is this something I could do purely in SQL?
Just an untested quick shot, sorry, but I think you could do something like
SELECT * FROM table GROUP BY REPLACE(text, 'sth', '')
You can use SOUNDEX. So with the examples that you gave, these queries:
SELECT SOUNDEX('test')
SELECT SOUNDEX('test sth')
SELECT SOUNDEX('is (sth) it?')
SELECT SOUNDEX('is it?')
return these results:
T230
T230
I200
I200
That means that the first two and the second two sound like each other. What I can't be sure of is how well this will work with your actual data, you're just going to have to try it.

Selecting rows based upon a search string or any of its synonyms

I need some help please...
I have 2 tables, one contains a description field which is entered freehand by the user, the second table is made up of 2 columns, the first is a group name and the second is a list of synonyms. So, for example, I might have three rows in the synonyms table in a group called A that contains the synonyms 'Leaflet', 'Brochure', 'Hand Bill'.
What I need to do is return all rows from the first table where the ItemDescription column contains any of the synonyms of the query variable which might be 'Leaflet'.
So this should give me all of the rows that contain anywhere in the long description field the words 'Leaflet', 'Brochure' or 'Hand Bill'.
I have been able to do this only where the ItemDescription field contains only actual words being looked for, in reality this os a long wordy column that may contain 50 or 60 words any one of which may be one of the search word or any of its synonyms.
All help gratefully received as always.
Thanks.
You should probably try to use LIKE or RLIKE to match the description column. In this case, you want to match a number of alternatives, so I'll just show an example.
Let us assume that we have this table containing synonyms. Note that we have added the word itself as a synonym:
+---------+-----------+
| word | synonym |
+---------+-----------+
| leaflet | leaflet |
| leaflet | brochure |
| leaflet | hand bill |
| skin | skin |
| skin | leather |
| skin | hide |
+---------+-----------+
You don't give an example table, so I invented one called items:
+---------+-------------------+-----------------------------------+
| item_id | brief | description |
+---------+-------------------+-----------------------------------+
| 1 | Diamond | This brochure is glossy and shiny |
| 2 | Halloween Special | A leaflet for the Halloween |
| 3 | Pumpkin | This is just a Halloween pumpkin |
+---------+-------------------+-----------------------------------+
Now, we assume that you want to look for all rows containing one of the synonyms of 'leaflet' in the description. The following query does the job:
SELECT * FROM items
WHERE description RLIKE (
SELECT
CONCAT('.*(', GROUP_CONCAT(synonym SEPARATOR '|'), ').*')
FROM synonyms
WHERE word = 'leaflet'
GROUP BY word
);
The inner select create a regular expression matching one of the synonyms, and the outer select applies this regular expression to the description column of our items table.
Thanks for the feedback. I have found an answer to my SQL needs:
SELECT *
FROM MainTable a
WHERE EXISTS
(
SELECT 1
FROM (
Select concat('%',Synonym,'%') As cond
From synonyms
Where Synonym Like '%SearchString%'
OR ListRef = ( Select ListRef
From synonyms
Where Synonym Like '%SearchString%')
) с
WHERE a.Description LIKE cond
)
OR ItemDescription Like '%SearchString%'
Without the final OR I was only returning rows where something existed in the synonyms table for my search string, with the OR it also returns all straight matches not found through synonyms.

How do I resolve or avoid need for MySQL with multiple AUTO INCREMENT columns?

I have put a lot of effort into my database design, but I think I am
now realizing I made a major mistake.
Background: (Skip to 'Problem' if you don't need background.)
The DB supports a custom CMS layer for a website template. Users of the
template are limited to turning pages on and off, but not creating
their own 'new' pages. Further, many elements are non editable.
Therefore, if a page has a piece of text I want them to be able to edit,
I would have 'manually' assigned a static ID to it:
<h2><%= CMS.getDataItemByID(123456) %></h2>
Note: The scripting language is not relevant to this question, but the design forces
each table to have unique column names. Hence the convention of 'TableNameSingular_id'
for the primary key etc.
The scripting language would do a lookup on these tables to find the string.
mysql> SELECT * FROM CMSData WHERE CMSData_data_id = 123456;
+------------+-----------------+-----------------------------+
| CMSData_id | CMSData_data_id | CMSData_CMSDataType_type_id |
+------------+-----------------+-----------------------------+
| 1 | 123456 | 1 |
+------------+-----------------+-----------------------------+
mysql> SELECT * FROM CMSDataTypes WHERE CMSDataType_type_id = 1;
+----------------+---------------------+-----------------------+------------------------+
| CMSDataType_id | CMSDataType_type_id | CMSDataType_type_name | CMSDataType_table_name |
+----------------+---------------------+-----------------------+------------------------+
| 1 | 1 | String | CMSStrings |
+----------------+---------------------+-----------------------+------------------------+
mysql> SELECT * FROM CMSStrings WHERE CMSString_CMSData_data_id=123456;
+--------------+---------------------------+----------------------------------+
| CMSString_id | CMSString_CMSData_data_id | CMSString_string |
+--------------+--------------------------------------------------------------+
| 1 | 123456 | The answer to the universe is 42.|
+--------------+---------------------------+----------------------------------+
The rendered text would then be:
<h2>The answer to the universe is 42.</h2>
This works great for 'static' elements, such as the example above. I used the exact same
method for other data types such as file specifications, EMail Addresses, Dates, etc.
However, it fails for when I want to allow the User to dynamically generate content.
For example, there is an 'Events' page and they will be dynamically created by the
User by clicking 'Add Event' or 'Delete Event'.
An Event table will use keys to reference other tables with the following data items:
Data Item: Table:
--------------------------------------------------
Date CMSDates
Title CMSStrings (As show above)
Description CMSTexts (MySQL TEXT data type.)
--------------------------------------------------
Problem:
That means, each time an Event is created, I need to create the
following rows in the CMSData table;
+------------+-----------------+-----------------------------+
| CMSData_id | CMSData_data_id | CMSData_CMSDataType_type_id |
+------------+-----------------+-----------------------------+
| x | y | 6 | (Event)
| x+1 | y+1 | 5 | (Date)
| x+2 | y+2 | 1 | (Title)
| x+3 | y+3 | 3 | (Description)
+------------+-----------------+-----------------------------+
But, there is the problem. In MySQL, you can have only 1 AUTO INCREMENT field.
If I query for the highest value of CMSData_data_id and just add 1 to it, there
is a chance there is a race condition, and someone else grabs it first.
How is this issue typically resolved - or avoided in the first place?
Thanks,
Eric
The id should be meaningless, except to be unique. Your design should work no matter if the block of 4 ids is contiguous or not.
Redesign your implementation to add the parts separately, not as a block of 4. Doing so should simplify things overall, and improve your scalability.
What about locking the table before writing into it? This way, when you are inserting a row in the CMSData table, you can get the last id.
Other suggestion would be to not have an incremented id, but a unique generated one, like a guid or so.
Lock Tables