We have a drug column in our database and this contains the Drug Name (e.g. Xanax) and its size (0.5mg).
E.g. Drug Name: Xanax 0.5mg
However, there's a need for us to separate the two data without creating a new column for the size as doing so will have a huge effect on the database structure. We just need to populate a list with just the drug name without its size based from this single field / column.
Is there a way to extract just the name of the drug? Let's say by forcing the user to add a parenthesis around the drug size (e.g. Xanax (0.5mg))? Meaning just extract all the string that comes before the first "(" character?
Or is there a better way?
Try this:
mytable:
id name
1 Xanax (0.5mg)
Query:
select id, substring_index(name,'(',1) from tb_mx;
Will return:
1, Xanax
So use it accordingly.
You can store drugĀ“s data in JSON format
{"some_unique_id":{
"name": "Xanax",
"quantity": "0.5mg"
}}
And then use Functions That Search JSON Values for MySQL 5.7 to get what parameter you need.
I have some experience with DB used in Pharma industry and I can say it's not ok do doit like that.
Here is what i think u must do (normalize)
Table UM (like mg,ml,etc)
Table Packing (like quantity per pice, pice nr , FK ID_UM)
Table Drugs (name, fk id_packing)
Don't worry about space. Tables UM and Packing will have alot of reused ID, and a column int take less that than varchar.
Or can used JSON ideea, but then you will have some problemes in reporting part.
Related
shouid i use concate operator or format?
No. If you want to provide a reliable, expandable schema then store the value as valueand the currency as code in your data table.
Build an ISO 4217 table for the currencies and its symbols.
Then build a view that joins your value and ISO 4217 tables that transforms your value to a string for output formatting.
If you want to store values with dollar sign, the valid-relational-way of doing that will be to add a table with currencies (columns: id, name, sign) and put dollar in that table. In the table with prices you can refer to that table to link numbers with currencies.
If you want to query data like that use select concat('$', number) from table;
I have a database listing campsites
There is a main table tblSites that contains the unique data eg name, coordinates, address etc and also includes columns for each facility eg, Toilet, Water, Shower, Electric etc where these are just 1=Yes, Null= no
This would be searched by something like
SELECT id FROM tblSites WHERE Water = 1 AND Toilets = 1
There is another related table tblLocations which contains location type (ie Near the sea, Rural, Mountains, By a river etc.
This means the table has a lot of columns and doesn't allow for easy updating if I want to add a new category.
This would be included in a search like this
SELECT M.id, L.* FROM tblSites AS M
LEFT JOIN tblLocation AS L ON M.ID = L.ID WHERE M.water=1 AND L.river=1
What I am considering is adding a column eg facilities that would contain an json string of facilities as a numbered key eg [1,3,4,12] each of the numbers represents an available facility, and another column for locations in the same format eg [1,3,5]
THis does allow me to reduce the table size and add additional facilities or locations without adding extra columns but is it a good idea performance wise?
i.e. a search would now be something like
SELECT id FROM tblSites WHERE (facilities LIKE '%1,%' AND facilities LIKE '%4,%' AND locations LIKE '%1,%')
Is there a better query that could be used to see if the field contains a key number in the array string?
Your WHERE clause is not working fine while using like '%1,%'.
if your facilities is string (TEXT or varchar ...) and searching value in stringed json array [2,3,12,21,300], where facilities like '%1,%' is true and matching with '21,' and if you want find where facilities like '%300,%' it never match that mentioned array!
So, searching json array in string format is rejected.
if your MySQL version is greater than 5.7.8, it supports native json as JSON type for columns.
When you store your data in json column in MySQL (by JSON_INSERT()) you're able to search them in where by WHERE JSON_CONTAINS(facilities,1)
But the best solution is re-design your table structures and relations as #Robby commented below your question.
I have downloaded a MySQL table as CSV, which has over thousand entries of the following type:
id,gender,garment-color
1,male,white
2,"male,female",black
3,female,"red,pink"
Now, when I am trying to create a chart out of this data, it is taking "male" as one value, and "male,female" as a separate value.
So, for the above example, rather than counting 2 "male", and 3 "female", the chart is showing 3 separate categories ("male", "female", "male,female"), with one count each.
I want the output as follows, for chart to have the correct count:
id,gender,garment-color
1,male,white
2,male,black
2,female,black
3,female,red
3,female,pink
The only way I know is to copy the row in MS Excel and adjust the values manually, which is too tedious for 1000+ entries. Is there a better way?
From MySQL command line or whatever tool you are using to send queries to MySQL:
select * from the_table
into outfile '/tmp/out.txt' fields terminated by ',' enclosed by '"'
Then download /tmp/out.txt' from the server and it should be good to go assuming your data is good. If it is not, you might need to massage it with some SQL function use in theselect`.
The csv likely came from a poorly designed/normalized database that had both those values in the same row. You could try using selects and updates, along some built in string functions, on such rows to spawn additional rows containing the additional values and update their original rows to remove those values; but you will have to repeat until all commas are removed (if there is more than one in some field), and will have to determine if a row containing multiple fields with such comma-separated lists need multiplied out (i.e. should 2 gender and 4 color mean 8 rows total).
More likely, you'll probably want to create additional tables for X_garmentcolors, and X_genders; where X is whatever the original table is supposed to be describing. These tables would have an X_id field referencing the original row and a [garmentcolor|gender] value field holding one of the values in the original rows lists. Ideally, they should actually reference [gender|garmentcolor] lookup tables instead of holding actual values; but you'd have to do the grunt work of picking out all the unique colors and genders from your data first. Once that is done, you can do something like:
INSERT INTO X_[garmentcolor|gender] (X_id, Y_id)
SELECT X.X_id, Y.Y_id
FROM originalTable AS X
INNER JOIN valueTable AS Y
ON X.Y_valuelist LIKE CONCAT('%,' Y.value) -- Value at end of list
OR X.Y_valuelist LIKE CONCAT('%,' Y.value, ',%') -- Value in middle of list
OR X.Y_valuelist LIKE CONCAT(Y.value, ',%') -- Value at start of list
OR X.Y_valuelist = Y.value -- Value is entire list
;
I have a situation where i need to store "Error Type" which has following options
I want to know what is the best way I should use to create my table "Error".
So either I take a "VARCHAR" data type and store values like "1,3,4" (Comma Separated) if "Take Off, Details and Legend" is selected and parse it when getting in view
OR
Take separate column for each field in table with data type "TINYINT" like "IsTakeOff" , "IsSpecifications" ,"Details" etc.
Please advice
Thanks
If user with id 1 select 1,3 and 4 then you can use following
Don't use multiple columns unless you are very confident the number won't grow.
Otherwise use a many-to-many association table - one with columns for the id of the item and the id of the error
One way to go might be to do it as an int and then in your code do something like this PHP, I don't know language you are using but most languages have a switch so it shouldn't be to hard to translate to another language.
$row // The row from the database.
switch ($row['Error_Type'])
{
case ('0'):
{
// Do something.
break;
}
...
}
You can use comma seperated column here that is varchar because you know that no of records will not grow here. And this is limited to only 5 values. And while searching the field you can use MySQL FIND_IN_SET which is very effective for this kind of situations. FIND_IN_SET will take two parameters. Your search keyword and the comma seperated string.
I'm looking for both MySQL and PostgreSQL solutions for this kind of problem.
Say I have a number of records with a title field. The titles are book or movie titles, like "The Cat in the Hat" and "Robin Hood". But while the titles must be displayed in their original form, they ought to be sorted in the way that libraries sort them, which is by moving any article, like "The" or "An" to the end of the title.
So "The Cat in the Hat" is sorted as if it were "Cat in the Hat, The".
What's the best way either to design the schema or write the query so that these records are sorted by title in the same way that libraries sort the title? (I also wish I knew the technical term for this type of ordering by title.) Also, what performance considerations should I be aware of and what indexes should I create?
Why don't you just add a "title_prefix" field to the table and move all these "the" and "a" strings there? When you're ordering you would use the "title" field, and when you are presenting the title you could do the concatenation in any way you wish.
Create a custom function that (sortableTitle, perhaps?) that will modify strings starting with your unwanted words. Finish your query statement with order by sortableTitle(title). This will incur an extra CPU cost, though you'll have to benchmark to know how much so.
You could create an extra column (sortTitle) that is populated by a trigger. This will take up some space, but then your server will be able to sort rows by an index.
Excepting the above, you cannot (without modifying the database server code) directly create an index that is in the order you want. As far as I can tell, that applies to both MySQL and PostgreSQL.
iTunes achieves this by having a second field in which the title is stored in the desired sorting format and sorting on this instead of title. It does sound like the cheap way out, but when you consider the performance implications of doing string manipulations on every title every time you do a select statement that orders by title, against doing string manipulations each time you insert or update the title, it does make sense.
Select * from TitleTable
Order by
Case when substring(title,0,4) = 'The ' then substring(title, 4, len(title)-4)
when substring(title,0,3) = 'An ' then substring(title, 3, len(title)-3)
when substring(title,0,2) = 'A ' then substring(title, 2, len(title)-2)
else title
end
I would suggest you split the title field in two fields: mainTitle and pre.
When a title is added, check if it starts with "A", "The" or other prefixes and split it (perhaps with a trigger) into the two fields. Your table would look like this:
| pre | mainTitle |
|-----|----------------|
| The | Cat in the Hat |
| A | Space Odyssey |
| | Eyes Wide Shut |
So, you can have an index on the mainTitle field and use it for sorting.
When you want to show the full title, concat the two fields, in either of the two forms.
If you choose this way, you'll have to modify accordingly the code for when a user gives a title to search in your table. The given title will have to be split the same way before searching the mainTitle field.
You'll have to be very, very careful with the code (trigger or other) that does the spliting so some special cases are caught correctly. You wouldn't want to have the A = B or the A B C: learn the alphabet books shown and sorted as = B, A and B C: learn the alphabet, A