I have a field in my database named "price" and it setup as varchar. It contains dollar sign as well as commas.
The values in my database are like this:
$100,000
$625,005
$115,990
$2,450,000
$137,005
and I would like it to order it like this:
$100,000
$115,990
$137,005
$625,005
$2,450,000
I tried ORDER BY 0+price and ORDER BY ABS(price) but they just outputted in the order it was in the database. Is there anyway to order this while keeping the field varchar
If at all possible, change your database to hold those values in a int, float or decimal field, depending on how much precision you need. Add the $ and all other formatting when outputting the values.
Everything else is just duct-taping around a bad database structure. It's not impossible, but it should be the very last resort when there is absolutely no way to change the database.
Fully agreeing with the above posts regarding the database design, there is a bad way anyways:
SELECT REPLACE(REPLACE(price,',',''),'$','') as cleanPrice FROM Table ORDER BY cleanPrice
The query has to do the replacements on every single row and therefore might become very slow..
Honestly you should really store these as int's and format them in PHP when you bring them out of the database, that way it's easier to work with the data and you can manipulate them as INT's.
When you pull them out you can use numeric_format to auto-add the comma's and then just add a $ infront of the price.
If you are storing multiple types of price's you can store a Currency Type in the DB too; which in this case would be USD.
I did this in Oracle quickly, so it might not work in MySQL...if not, I'm sorry. I'm only selecting the prices
select price
from table
order by (cast(substr(replace( replace('price', ',', ''), '"', '' ), 2, length(replace( replace('price', ',', ''), '"', '' ))-1) as int)
If you don't have any way of changing the DB structure you can add a computed column to the table for sorting purposes.
Unfortunately, mysql does not support computed columns, so after you create the new column you would need to add triggers (on UPDATEs and INSERTs) to compute the value for every inserted/changed row on the table.
In your trigger you would use REPLACE(REPLACE(price,'$',''),',','') for the value of the new column.
You could also create a view that has this logic in it and select from that.
The mysql documenation for creating triggers is located here
The mysql documenation for using views is located here
Related
It's highly likely this has been answered elsewhere, I can't find anything so if you can link to another post that would be ace.
I have a MySQL table which lists tickets and payments, amongst other columns. I didn't design table and I can't change too much; adding a column is out of the question. Here's a simplified version of the table:
CREATE TABLE cases (
id INT PRIMARY,
created TIMESTAMP, -- when created in db- each day the table is truncated and a new csv imported
opened DATE, -- will differ from the timestamp, this is the column I want to group by
total DECIMAL, -- not relevant in this question but i'm totaling this by month too
tickets VARCHAR(256) -- the one I want to count, two tickets would look like '"foo1234","baa5678"', there is no pattern (i.e. Same prefix) in the tickets either
);
The tickets column references possibly multiple tickets. Each is wrapped in double quotes in the DB (I have a feeling this is a bit insecure, not my decision and I can't really change it), with each reference separated by a comma (if there is more than one).
There are other columns like client name and date closed, but they are irrelevant in this case
I've written a query which will group the rows by month, year and total the payments for each month.
I want the results to also include the count of tickets, itemized monthly. It can be assumed that there will always be at least one ticket. On the front end I either count the commas and add one, or explode by comma and count the array which works fine for a hand full of rows (there are rarely more than 4 tickets in one row), but as this will form a report of the entire database I want it to be a bit more efficient.
I don't have any code to post (I'm not looking for someone to write it for me, just point me in the right direction, maybe there is a method i'm forgetting?), as I'm not really sure where to start with it, all other posts similar to this are about grouping and totaling numbers (which I also need to do but i'm ok with that part), but nothing on how to do it with a string. SUM(), but with a string.
This is easily solved by using CONCAT_WS, read more about it here
CONCAT_WS will concatenate the strings with a seperator chosen by you, in your case you would do that with a comma: CONCAT_WS(',',string_column)
This wil give you a all the strings separated by commas. if you really need the count than you can continue with this: How to count items in comma separated list MySQL
Using this would give:
LENGTH(CONCAT_WS(',',string_column)) - LENGTH(REPLACE(CONCAT_WS(',',string_column), ',', ''))+1
+1 because you need have one more result than you have comma's
So I've got a field in my database that will contain serial id numbers separated by commas eg. 2817,2385,4937,3298 I want to be able to add more numbers to the same field over time.
The best way I can think to do this is to get the contents, add the new numbers to it, and insert them back into the database.
What I'm wondering is if there's a more direct way. I had trouble thinking of a good way to word this that yields helpful search results so I'm asking here.
Yes there is.
UPDATE `table` SET `column` = CONCAT(`column`,',new_serial')
However this is not right, you should never store comma separated values. It's called database normalization.
Try this:
UPDATE `tableName` SET `yourColum` = CONCAT(`yourColumn`, ',nextId')
This will update your column as you requested.
i need to sort through a column in my database, this column is my category structure the data thats in the column is city names but not all the names are the same for each city, what i need to do is go through the values in the column i may have 20-40 value that are the same city but written differently i need a script that can interpret them and change them to a single value
so i may have two values in the city column say:( england > london ) and ( westlondon ) but i need to change to just london, is there a script out there that is capable of interpreting the values that are already there and change them to the value would want i know the dificult way of doing this one by one but wondered if there was a script in any language that could complete this
I've done this sort of data clean-up plenty of times and I'm afraid I don't know of anything easier than just writing your own fixes.
One thing I can recommend is making the process repeatable. Have a replacement table with something like (rulenum, pattern, new_value). Then, work on a copy of the relevant bits of your table so you can just re-run the whole script.
Then, you can start with the obvious matches (just see what looks plausible) and move to more obscure ones. Eventually you'll have 50 without matches and you can just manually patch entries for this.
Making it repeatable is important because you'll be bound to find mis-matches in your first few attempts.
So, something like (syntax untested):
CREATE TABLE matches (rule_num int PRIMARY KEY, pattern text, new_value text)
CREATE TABLE cityfix AS
SELECT id, city AS old_city, '' AS new_city, 0 AS match_num FROM locations;
UPDATE c SET c.new_city = m.new_value, c.match_num = m.rule_num
FROM cityfix AS c JOIN matches m ON c.old_city LIKE m.pattern
WHERE c.match_num = 0;
-- Review results, add new patterns to rule_num, repeat UPDATE
-- If you need to you can drop table cityfix and repeat it.
Just an idea: 16K is not so much. first use Perl's DBI (im assuming you are going to use Perl) to fetch that city column, store it in a hash (city name as the hash), then find your an algorithm that suites your needs (performance wise) to iterate over the hash keys and use String::Diff to find matching intersection (read about it, it definitely can help you out) and store it as a value.. then you can use that to update the database using the key (old value) and the value as the new value to update.
I have a tab delimited text file with the first row being label headings that are also tab delimited, for example:
Name ID Money
Tom 239482 $2093984
Barry 293984 $92938
The only problem is that there are 30 some columns instead of 3 so I'd rather not have to type out all the (name VARCHAR(50),...) if it's avoidable.
How would I go about writing a function that creates the table from scratch in php from the text file, and say the function takes in $file_path and $table_name? Do I have to write all the column names again telling mysql what type they are and chop off the top or is there a more elegant solution when the names are already there?
You would somehow need to map the column type to the columns in your file. You could do this by adding that data to your textfile. For instance
Name|varchar(32) ID|int(8) Money|int(10)
Tom 239482 $2093984
Barry 293984 $92938
or something similar. Then write a function thet get's the column name and columntype using the first line and the data to fill the table with using all the other rows. You might also want to add a way to name the given table etc. However, this would probably be as much work (if not more) than creating SQL queries using you text file. Add a create table statement at the top and insert statements for each line. With search and replace this could be done very fast.
Even if you could find a way to do this, how would you determine the column type? I guess there would be some way to determine the type of the columns through checking for certain attributes (int, string, etc). And then you'd need to handle weird columns like Money, which might be seen as a string because of the dollar sign, but should almost certainly be stored as an integer.
Unless you plan on using this function quite a bit, I wouldn't bother spending time cobbling it together. Just fat finger the table creation. (Ctrl-C, Ctrl-V is your friend)
I have a field in a table recipes that has been inserted using mysql_real_escape_string, I want to count the number of line breaks in that field and order the records using this number.
p.s. the field is called Ingredients.
Thanks everyone
This would do it:
SELECT *, LENGTH(Ingredients) - LENGTH(REPLACE(Ingredients, '\n', '')) as Count
FROM Recipes
ORDER BY Count DESC
The way I am getting the amount of linebreaks is a bit of a hack, however, and I don't think there's a better way. I would recommend keeping a column that has the amount of linebreaks if performance is a huge issue. For medium-sized data sets, though, I think the above should be fine.
If you wanted to have a cache column as described above, you would do:
UPDATE
Recipes
SET
IngredientAmount = LENGTH(Ingredients) - LENGTH(REPLACE(Ingredients, '\n', ''))
After that, whenever you are updating/inserting a new row, you could calculate the amounts (probably with PHP) and fill in this column before-hand. Or, if you're into that sort of thing, try out triggers.
I'm assuming a lot here, but from what I'm reading in your post, you could change your database structure a little bit, and both solve this problem and open your dataset up to more interesting uses.
If you separate ingredients into its own table, and use a linking table to index which ingredients occur in which recipes, it'll be much easier to be creative with data manipulation. It becomes easier to count ingredients per recipe, to find similarities in recipes, to search for recipes containing sets of ingredients, etc. also your data would be more normalized and smaller. (storing one global list of all ingredients vs. storing a set for each recipe)
If you're using a single text entry field to enter ingredients for a recipe now, you could do something like break up that input by lines and use each line as an ingredient when saving to the database. You can use something like PHP's built-in levenshtein() or similar_text() functions to deal with misspelled ingredient names and keep the data as normalized as possbile without having to hand-groom your [users'] data entry too much.
This is just a suggestion, take it as you like.
You're going a bit beyond the capabilities and intent of SQL here. You could write a stored procedure to scan the string and return the number and then use this in your query.
However, I think you should revisit the design of whatever is inserting the Ingredients so that you avoid searching strings in of every row whenever you do this query. Add a 'num_linebreaks' column, calculate the number of line breaks and set this column when you're adding the Indgredients.
If you've no control over the app that's doing the insertion, then you could use a stored procedure to update num_linebreaks based on a trigger.
Got it thanks, the php code looks like:
$check = explode("\r\n", $_POST['ingredients']);
$lines = count($check);
So how could I update all the information in the table so Ingred_count based on field Ingredients in one fellow swoop for previous records?