SQL Padding with zeros(LPAD) in a Database independent way - mysql

I have a table like the following :
code ---> INTEGER
name ---> CHAR
+------+------+
| code | name |
+------+------+
| 1 | aa |
| 2 | bb |
| 3 | cc |
I want to pad with left zeros the code field in this way :
SELECT LPAD(code,5,'0') FROM table;
This query works well in MySQL but it doesn't work on SQL Server and on PostgreSQL, i'm looking for a query that work on all databases or at least on these four :
MySQL
PostgreSQL
MSSQL
Firebird
without any changes . Is there a solution ?

The correct answer is "do this in your client".
There is no single solution at the RDBMS level
However, for SQL Server 2012 (yes, next release), PostgreSQL and MySQL you can do this:
RIGHT(CONCAT('00000', code), 5)
Newer PostgreSQL does have LPAD, SQL Server doesn't
The various FORMAT functions are incompatible (but again need to wait until SQL Server 2012)
The RIGHT is consistent, but string concatenation operators are different
The CONCAT function is added in SQL Server 2012

Kind of weak, but one option is to prepend a number of zeroes to the front, and then take the last x characters from the right.
For example,
select '0000000000' || code from table;
will produce
00000000001
00000000002
00000000003
Then substring the results would give you
select substr('0000000000' || code, -5) from table;
00001
00002
00003
I can't recall if the concatenate and substring functions are the same in those four databases. But I guessed that perhaps you are looking for a way to do it that is more generic than what you are already doing, and that might be it. Apologies for the overall ugliness though.

In Firebird 2.5 you can use a query like this:
select right('00000' || cast(code as varchar(20)), 5) from table

Related

How to store and evaluate dynamic expressions in MySQL(or any other SQL)

Best way to store a dynamic expression in a table for each row for a searching module.
The expression is dynamic and can have multiple fields which are being compared.
I considered creating a separate column for each type of field and fattening out complex nested logic by getting all possible combinations using dnf and storing them in my table. The disadvantages of doing that is for every new logic and expression, a new column has to be created which would lead to a large table which has too many NULLS in it and also adding a new column would take time & refactoring(we are talking about more than 800 columns here).
The alternate approach which I think would work better is below->
I want to discuss if there are better way to this, and if not, how can we improve and achieve the below suggested approach.
| id | expression | diagnosis |
|------|------------------------------------------------|-------------|
| 1 |`p.age>12 and p.gender==Male` | diseaseA |
| 2 |`p.age>50 and p.bp>20` | diseaseB |
| 3 |`p.age<20 and p.bp<20` | diseaseC |
| 4 |`p.age<30 and p.age>20 and (p.bp<30 or p.bp>50)`| diseaseD |
I want to search in this table, for a patient p with certain properties (age=*something*,bp=*something*,etc).
The resulting rows should return all rows which satisfy the expression and also rows which partially match the expression(i.e the rows which are using properties not supplied in the search criteria).
For example for a search for patient p(age=22,bp=15), the search result should be
| id | disease |
|------|-------------|
| 1 | diseaseA |
| 3 | diseaseC |
| 4 | diseaseD |
Since I am new to SQL, the (newbie) way I think I can do this is
First get all the rows(in-memory would be costly, lets discuss what is best possible way to execute the below said functionality in point 2 row-by-row)
Then row-by-row transform the expression to a logical executable expression(which is later executed using eval) using regex matching & replacement(I hope there is a better way than this) for the search criteria(i.e. substituting the patient details) [in my example for the 2nd row, the expression p.age>50 and p.bp>20 gets converted to "22>50 && 15>20"]
All the rows for which the result of transforming & executing the result was true(or partially matched) should be returned.
The language is not an issue as I would be starting this project from scratch and can use any language
I can answer for MySQL.
First of all, you'll have to write all of your sql code inside sql procedure.
Generally you are interestedin dynamic SQL
https://dev.mysql.com/doc/refman/5.7/en/sql-syntax-prepared-statements.html
So a straight-forward approach is to open a a cursor for your table with expressions and for each expression replace p.age with it's actual value and then execute dynamic SQL. (select 22 > 50 and 15 > 20)
Another approach is to loop through expression table (open cursor for it) and as you probably have patient id (not only it's field values) just generate normal sql that selects from patient table (select patient_id from patients where [expression_from_expression_table] and patient_id = [your_known_patient_id])
And the third one that I can imagine is generating a big single query from whole expression table
select group_concat(concat('if(', expression, ',"', diagnosis, '", "") as ', diagnosis) separator ',') from expressions into somevar;
and then doing replace of p.* with actual values and executing second query:
set somevar = replace(somevar, 'p.age', '15');
...
#qry = concat('select ', somevar);
PREPARE qry FROM #qry;
EXECUTE qry;
The third approach is fastest to my mind but will require aditional work on client as you will recieve diagnosis as columns, not as rows.
But hope you get the general idea.

Select MySQL tables ending in _timestamp with matching regxp

I'm trying to isolate some tables in a mysql database that match a pattern which can be described as
some-name_10-digit timestamp
eg:
| oxseohistory_1381393508 |
| oxseohistory_1382427650 |
| oxseohistory_1382617597 |
Is there a way to use a regular expression which matches everything with 10 digits at the end? Like this one?
\d{10}$
I tried
SHOW TABLES FROM `usrdb_xxxx` WHERE `Tables_in_usrdb_xxxx` RLIKE '\d{10}$';
which did not work (empty set).
As MySQL does not support \d, you can use
[[:digit:]]{10}$
Or
[0-9]{10}$

How to perform arithmetic operation recorded in a field in a select with Mysql

I have a table lake that :
TABLE A
id | arithmetic | column2
1 |{id1}/{id2} | bla bla
2 |{id3}+{id5}*1000| other bla bla
3 | ...
another table - TABLE B
id | values |
1 | 4 |
2 | 7 |
3 | 0,25 |
...
I wanna take a QUERY that execute the arithmetic operator in TABLE A using values of TABLE B .
Considering I already have managed to make the replacement of the codes by the figures in table B , they are as string is read as a string and not as a number, if I use a CONVERT ( arithmetic , unsigned integer) , it does not execute the expression but yes transforms the numbers encontraods to the first mathematical operator .
I trying to use convert(#arithmetic, unsigned integer), but not sucessfull.
Like a example in a simple select :
Select '5+2', results '5+2';
but if I use select 5+2 , results 7.
therefore if I use select convert ( '5+2', unsigned integer); , results 5 ( read until the first character not mathematical).
In short words : read and execute a math expression wrote inside a field?
General notes
First thing first, make sure that you're not in the middle of XY-problem with your architecture. DBMS should not handle such logic solution in general, as the logic is not part of data, it should be part of application. However, even in application, you should avoid run-time evaluation as it in most cases not safe and unpredictable (thus, source from any kind of problems).
Solution with DBMS
While I would not recommend to go this way - with evaluation of expression on run-time, it is still possible with prepared statements, like:
SET #expr:=(
SELECT
GROUP_CONCAT(CONCAT('SELECT ', arithmetic, ' AS expr') SEPARATOR ' UNION ALL ') AS expr
FROM tableA
);
PREPARE execSelect FROM #expr;
EXECUTE execSelect;
Working fiddle is here. I may even imagine values substitution, but I would not recommend to go this way. If you really need this, then, most probably, something is wrong with architecture breakdown, since your data within SQL needs to hold some logic - and that's the goal for your application, not for your database.

Sort Array results based on variable Algorithm - MYSQL & PHP

I have an array nested within a PHP while loop that outputs a set of forum posts a number of times. I want to sort the array results based on an algorithm - however I do not want to hardcode the algorithm so I can test different variables at a later date. NB - I'm not looking to sort the items within the array, but rather the final output which when looped will output the array 20+ times.
Currently I have 2 Tables - the Forum table with loads of rows (3000 +):
id | name | date_add | votes | ... |
1 | Test Name | 1234567890 | 2 | ... |
... | ... | ... | ... | ... |
The other table contains the Algorithm variables that I want to pass through to the calculation and has only 1 row:
id | vote_reduction | time_variable | gravity |
1 | 1 | 2 | 1.8 |
The specific algorithm I'm using sorts the information based on how log it has been live (in hours), how many votes it has and the gravity factor makes it more sensitive to time. In full:
(votes - vote_reduction)/((Hours Live + time_variable) ^ gravity)
So far I've managed to get this far, and something is going wrong but I can't quite figure it out:
SELECT forum.*,
((forum.votes - algorithm.vote_reduction)/POW(((TIMESTAMPDIFF(HOUR, SYSDATE(), forum.date_add)) + algorithm.time_variable),algorithm.gravity)) AS algorithm.al,
forum.name, forum.id
FROM forum as forum
LEFT JOIN algorithm AS algorithm ON (algorithm.id='1')
ORDER BY algorithm.al
Any ideas?
I haven't tested the results of the algorithm, but the query returns a result for al if you just remove algorithm. from algorithm.al. I don't think you can make a column alias that acts like it's part of a table. What's confusing me is that you say that it's running on your machine. It's not running on SQL Fiddle and is throwing an error.
SELECT forum.*,
((forum.votes - algorithm.vote_reduction)/POW(((TIMESTAMPDIFF(HOUR, SYSDATE(), forum.date_add)) + algorithm.time_variable),algorithm.gravity)) AS al
FROM forum AS forum
LEFT JOIN algorithm AS algorithm ON (algorithm.id='1')
ORDER BY al
Link to SQL fiddle
There are a few errors in the code as follows:
Making an alias with the name "algorithm" clashes with a MySQL
clause also called ALGORITHM
The calculation (at least the way it is
edited above) creates too many values in the POW clause
Encapsulating all declared aliases in ' ' makes the code more full
proof - but the ORDER BY clause doesn't like quotation marks (so remove them there)
The SYSDATE() and forum.date_add fields are in different formats -
the latter being a timestamp
To fix:
SELECT forum.*, TIMESTAMPDIFF(HOUR, from_unixtime(bd.date_add), NOW()) as 'timedif'
((forum.votes - alg.vote_reduction)/POW(('timedif' + alg.time_variable),alg.gravity)) AS 'al'
FROM forum AS forum
LEFT JOIN algorithm AS 'alg' ON (alg.id='1')
ORDER BY al

SQL: to decide to use it or not

Hallo:
I did some text processing of a database using Shell and Python. For interoperability, I am thinking to do it using SQL. SQL is good for some query task. But i am not sure if the SQL can handle all my tasks. Consider one example database:
item | time | value
-----+------+-------
1 | 134 | 3
2 | 304 | 1
3 | 366 | 2
4 | 388 | 2
5 | 799 | 6
6 | 111 | 7
I need to profile the sum of #values over certain #time interval. Suppose the time interval is 100, the result should be:
time_interval | sumvalue
--------------+----------
1 | 10 -- the time interval from 100 to 199
3 | 5 -- the time interval from 300 to 399
7 | 6 -- the time interval from 700 to 799
I could not find a better way to do it from the SQL text book than to do it using shell and python.
So my SO friends, any suggestion?
Thanks!
You should be able to do it in mysql with a pretty simple query:
SELECT time DIV 100, SUM(value) FROM yourtable
GROUP BY time DIV 100
The query takes advantage of the fact that integer division by 100 will give you the interval groupings you have described (eg. 111 DIV 100 = 1 and 134 DIV 100 = 1)
Question is not clear to me.
There is a database and you want to process data from there, and you are asking to use or not to use SQL? Answer:Yes, SQL is an interface to many databases, it is quite standart for major databases with minor changes. Use it.
If you cannot decide to use or not to use a database for storing and processing some values, then data type, amount of data and relations in data is important. If you want to handle large amount of data and there is relation between datasets, then you may want to use relational database systems such as MySql. The problem you told is a very simple problem for RMDBS. Let me give an example:
select sum(value) from items where
time>=100 and time<=200
But if dataset is small you can easily handle it with file I/O.
If you will use Python, you may want to use Sqlite as database, it is very lightweight, simple, easy to use and widely used database. You can use SQL with Sqlite too.
If you can give clearer details, we can help more.
Yes, a SQL-based databased like MySQL will probably be a fine choice for your project. You may also want to look at SQLite if you don't want to have to set up a server.
A good introductory text on SQL would be helpful for you. I suggest SQL For Dummies by Allen Taylor.