I have a long list of strings in a column in various formats. I would like to search for that substring and then organize that column while leaving the original column.
There is one table with 8 columns, one of which contains strings. There is also a list of words in another table. I would like to match those the words in the list with those string as an additional column. This would be so in the large table of "Tom","tom","tom az", "Tom Hanks", would have another column that just has "Tom" (the corresponding match in the list) for all of them.
I have thought about using the JOIN function, but wasn't sure how to do that with substrings.
The excel logic would be something along the lines of "=IF((SEARCH("Tom","asfj Tom dsf")),"
TOM","NULL").
If there is more than one match is found, I would like to use the one with earlier 'ID' ( a column of integers from 1 - 11mil).
The question is still a bit ambiguous. You should really show the table structure, sample data and expected results.
Supposing you have this minimal structure and data:
CREATE TABLE People (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
FullName TEXT
);
INSERT INTO People (FullName) VALUES ('Tom Hanks');
INSERT INTO People (FullName) VALUES ('Mary 467');
INSERT INTO People (FullName) VALUES ('ann margaret' );
INSERT INTO People (FullName) VALUES ('ziddy tom');
INSERT INTO People (FullName) VALUES ('bloody mary');
INSERT INTO People (FullName) VALUES ('mary ann');
CREATE TABLE Names (
id INTEGER AUTO_INCREMENT PRIMARY KEY,
Name TEXT
);
INSERT INTO Names (Name) VALUES ('Tom' );
INSERT INTO Names (Name) VALUES ('Mary');
INSERT INTO Names (Name) VALUES ('Ann' );
... then you can get a first result with a query like this:
SELECT p.*, n.Name
FROM People p
JOIN Names n ON p.FullName LIKE CONCAT('%',LOWER(n.Name),'%');
(tested on SQLFiddle here)
There are some problems though.
It's not clear if you want to search whole word only. Your Excel sample does not do that, so I stuck with a simple LIKE. To search for whole words the LIKE will not work properly.
"mary ann" comes up twice because that FullName contains two of the Names. You said you'd like to choose one depending on ID, but it's not clear if you understood the problem.
Related
How can i insert multiple values into one row?
My query
insert into table_RekamMedis values ('RM001', '1999-05-01', 'D01', 'Dr Zurmaini', 'S11', 'Tropicana', 'B01', 'Sulfa', '3dd1');
i cant insert two values into one row. is there another way to do it?
I'm ignorant of the human language you use, so this is a guess.
You have two entities in your system. One is dokter, the other is script (prescription). Your requirement is to store zero or more scripts for each dokter. That is, the relationship between your entities is one-to-many.
In a relational database management system (SQL system) you do that with two tables, one per entity. Your dokter table will contain a unique identifier for each doctor, and the doctor's descriptive attributes.
CREATE TABLE dokter(
dokter_id BIGINT AUTO_INCREMENT PRIMARY KEY NOT NULL,
nama VARCHAR (100),
kode VARCHAR(10),
/* others ... */
);
And you'll have a second table for script
CREATE TABLE script (
script_id BIGINT AUTO_INCREMENT PRIMARY KEY NOT NULL,
dokter_id BIGINT NOT NULL,
kode VARCHAR(10),
nama VARCHAR(100),
dosis VARCHAR(100),
/* others ... */
);
Then, when a doctor writes two prescriptions, you insert one row in dokter and two rows in script. You make the relationship between script and dokter by putting the correct dokter_id into each script row.
Then you can retrieve this information with a query like this:
SELECT dokter.dokter_id, dokter.nama, dokter.kode,
script.script_id, script.kode, script.nama, script.dosis
FROM dokter
LEFT JOIN script ON dokter.dokter_id = script.dokter_id
Study up on entity-relationship data design. It's worth your time to learn and will enhance your career immeasurably.
You can't store multiple values in a single field but there are various options to achieve what you're looking for.
If you know that a given field can only have a set number of values then it might make sense to simply create multiple columns to hold these values. In your case, perhaps Nama obat only ever has 2 different values so you could break out that column into two columns: Nama obat primary and Nama obat secondary.
But if a given field could have any amount of values, then it would likely make sense to create a table to hold those values so that it looks something like:
NoRM
NamaObat
RM001
Sulfa
RM001
Anymiem
RM001
ABC
RM002
XYZ
And then you can combine that with your original table with a simple join:
SELECT * FROM table_RekamMedis JOIN table_NamaObat ON table_RekamMedis.NoRM = table_NamaObat.NoRM
The above takes care of storing the data. If you then want to query the data such that the results are presented in the way you laid out in your question, you could combine the multiple NamaObat fields into a single field using GROUP_CONCAT which could look something like:
SELECT GROUP_CONCAT(NamaObat SEPARATOR '\n')
...
GROUP BY NoRM
I am trying to display where a record has multiple categories though my query only appears to be showing the first instance. I need for the query to be displaying the domain multiple times for each category it appears in
The SQL statement I have is
SELECT domains.*, category.*
FROM domains,category
WHERE category.id IN (domains.category_id)
Which gives me the below results
You should not store numeric values in a string. Bad, bad idea. You should use a proper junction table and the right SQL constructs.
Sometimes, we are stuck with other people's bad design decisions. MySQL offers find_in_set() to help in this situation:
where find_in_set(category.id, domains.category_id) > 0
Use find_in_set().
SELECT domains.*, category.*
FROM domains,category
WHERE find_in_set (category.id ,domains.category_id)
But it is very bad db design to store fk as a csv.
As others have pointed out, you can use FIND_NI_SET() as a workaround to solve your problem.
My suggestion is that you refactor your code and database a bit. Storing values in CSV format stored in a single column is almost always a bad idea.
As Gordon Linoff correctly points out you'd be better off if you'd create an additional table to store the category_id values:
CREATE TABLE domain_categories (domain_id INT, category_id INT, PRIMARY KEY (domain_id, category_id));
That's assuming you want to enfore that each category is only stored once against each domain. If you don't, just drop the primary key.
You'd then insert your IDs into this new table:
INSERT INTO domain_categories (domain_id, category_id) VALUES (2,6),(2,8);
or
INSERT INTO domain_categories (domain_id, category_id) VALUES (4,3);
INSERT INTO domain_categories (domain_id, category_id) VALUES (4,11);
INSERT INTO domain_categories (domain_id, category_id) VALUES (20,3);
Now that you have properly stored the data you can easily query as needed:
SELECT domains.*,category,*
FROM domains
JOIN domain_category ON (domain_category.domain_id=domains.id)
JOIN category ON (category.id=domain_category.category_id);
Using MySQL quirks you can even show the category_id column in CSV format.
SELECT domains.*, GROUP_CONCAT(DISTINCT domain_category.category_id)
FROM domains
JOIN domain_category ON (domain_category.domain_id=domains.id)
GROUP BY domains.id;
I am doing an insert from an imported table and adding data into multiple tables using mysql.
Basically when doing the insert there are some null fields as the data has been imported from a csv.
What I want to do is extract the data and not create multiple null entries. An example is when adding contacts which have no entries. Basically I want to have one entry in the table which can be bound to the id within the table.
How can i do this?
My current code is
Insert into Contact(FirstName, Surname, Position, TelephoneNo, EmailAddress, RegisteredDate)
Select Distinct Import.FirstName, Import.SecondName, Import.JobTitle,
Import.ContactTelNumber, Import.EmailAddress, Import.RegistrationDate
FROM Import
This basically imports and does no checks but where can I add check for this?
It's hard to infer exactly what you mean from your description. It would help if you showed a couple of example lines, one that you want included and one that you want to be excluded.
But you can add a variety of conditions in the WHERE clause of your SELECT. For example, if you just want to make sure that at least one column in Import is non-null, you could do this:
INSERT INTO Contact(FirstName, Surname, Position, TelephoneNo,
EmailAddress, RegisteredDate)
SELECT DISTINCT FirstName, SecondName, JobTitle,
ContactTelNumber, EmailAddress, RegistrationDate
FROM Import
WHERE COALESCE(FirstName, SecondName, JobTitle, ContactTelNumber,
EmailAddress, RegistrationDate) IS NOT NULL
COALESCE() is a function that accepts a variable number of arguments, and returns the first non-null argument. If all the arguments are null, it returns null. So if we coalesce all the columns, and we get a null, then we know that all the columns are null, and we exclude that row.
Re your comment:
Okay, it sounds like you want a unique constraint over the whole row, and you want to copy only rows that don't violate the unique constraint.
One way to accomplish this would be the following:
ALTER TABLE Contact ADD UNIQUE KEY (FirstName, Surname, Position, TelephoneNo,
EmailAddress, RegisteredDate);
INSERT IGNORE INTO Contact(FirstName, Surname, Position, TelephoneNo,
EmailAddress, RegisteredDate)
SELECT DISTINCT FirstName, SecondName, JobTitle,
ContactTelNumber, EmailAddress, RegistrationDate
FROM Import;
The INSERT IGNORE means if it encounters an error like a duplicate row, don't insert it, but also don't abort the insert for other rows.
The unique constraint creates an index, so it will take some time to run that ALTER TABLE, depending on the size of your table.
Also it may be impractical to have a key containing many columns. Indexes have a limit of 16 columns and 1000 bytes total in length. However, I would expect that what you really want is to restrict to one row per EmailAddress or some other subset of the columns.
I need to add data to a MySQL database like that:
Person:
pId, nameId, titleId, age
Name:
nameId, name
Title:
titleId, title
I don't want to have any names or title more then once in the db so I didn't see a solution with LAST_INSERT_ID()
My approach looks like that:
INSERT IGNORE INTO Name(name) VALUES ("Peter");
INSERT IGNORE INTO Title(title) VALUES ("Astronaut");
INSERT INTO Person(nameId, titleId, age) VALUES ((SELECT nameId FROM Name WHERE name = "Peter"), (SELECT nameId FROM Name WHERE name = "Astronaut"), 33);
But I guess that's a quite dirty approach!?
If possible I want to add multiple persons with one query and without having anything more then one times in db.
Is this possible in a nice way? Thanks!
You could put title and name as two columns of your table and then:
set one UNIQUE index on each column if you don"t want to have two titles or two names identical in the DB
or set an UNIQUE index on (title,name) if you don't want to have two entries having both the same name and the same title.
If you really want to have separate tables, you could do as you suggested in your post, but wrapping all your insert statements in a TRANSACTION to allow rollback if you detect a duplicate somewhere.
See Design dilemma: If e-mail address already used, send e-mail "e-mail address already registered", but can't because can't add duplicate to table which appear to be exactly the same problem, but having name & email instead of name & titles.
START TRANSACTION;
INSERT INTO title(value) VALUES ("Prof.");
SELECT LAST_INSERT_ID() INTO #title_id;
-- Instead of using user-defined variable,
-- you should be able to use the last_insert_id
-- equivalent from the host language MySQL driver.
INSERT INTO username(value) VALUES ("Sylvain");
SELECT LAST_INSERT_ID() INTO #username_id;
-- Instead of using user-defined variable,
-- you should be able to use the last_insert_id
-- equivalent from the host language MySQL driver.
INSERT INTO account(username_id, email_id) VALUES (#username_id,#title_id);
COMMIT;
See LAST_INSERT_ID()
A third solution would be to SELECT before doing you insert to see in the entry are already present. But personally I wouldn't push to the check-before-set approach at the very least, this will require an extra query which is mostly superfluous if you use correctly indexes.
I'm using MySQL 4.1. Some tables have duplicates entries that go against the constraints.
When I try to group rows, MySQL doesn't recognise the rows as being similar.
Example:
Table A has a column "Name" with the Unique proprety.
The table contains one row with the name 'Hach?' and one row with the same name but a square at the end instead of the '?' (which I can't reproduce in this textfield)
A "Group by" on these 2 rows return 2 separate rows
This cause several problems including the fact that I can't export and reimport the database. On reimporting an error mentions that a Insert has failed because it violates a constraint.
In theory I could try to import, wait for the first error, fix the import script and the original DB, and repeat. In pratice, that would take forever.
Is there a way to list all the anomalies or force the database to recheck constraints (and list all the values/rows that go against them) ?
I can supply the .MYD file if it can be helpful.
To list all the anomalies:
SELECT name, count(*) FROM TableA GROUP BY name HAVING count(*) > 1;
There are a few ways to tackle deleting the dups and your path will depend heavily on the number of dups you have.
See this SO question for ways of removing those from your table.
Here is the solution I provided there:
-- Setup for example
create table people (fname varchar(10), lname varchar(10));
insert into people values ('Bob', 'Newhart');
insert into people values ('Bob', 'Newhart');
insert into people values ('Bill', 'Cosby');
insert into people values ('Jim', 'Gaffigan');
insert into people values ('Jim', 'Gaffigan');
insert into people values ('Adam', 'Sandler');
-- Show table with duplicates
select * from people;
-- Create table with one version of each duplicate record
create table dups as
select distinct fname, lname, count(*)
from people group by fname, lname
having count(*) > 1;
-- Delete all matching duplicate records
delete people from people inner join dups
on people.fname = dups.fname AND
people.lname = dups.lname;
-- Insert single record of each dup back into table
insert into people select fname, lname from dups;
-- Show Fixed table
select * from people;
Create a new table, select all rows and group by the unique key (in the example column name) and insert in the new table.
To find out what is that character, do the following query:
SELECT HEX(Name) FROM TableName WHERE Name LIKE 'Hach%'
You will se the ascii code of that 'square'.
If that character is 'x', you could update like this:(but if that column is Unique you will have some errors)
UPDATE TableName SET Name=TRIM(TRAILING 'x' FROM Name);
I'll assume this is a MySQL 4.1 random bug. Somes values are just changing on their own for no particular reason even if they violates some MySQL constraints. MySQL is simply ignoring those violations.
To solve my problem, I will write a prog that tries to resinsert every line of data in the same table (to be precise : another table with the same caracteristics) and log every instance of failures.
I will leave the incident open for a while in case someone gets the same problem and someone else finds a more practical solution.