How to create MySQL friendly view from a query result - mysql

How can I create a friendly view from MySQL query results like this image's examples to propose questions here, at stackoverflow, that are relationated with MySQL database problems.
I don't even know if friendly view is the correct term for this. But every time that I have to show my mysql table's data, I draw this information manualy.
I do something like this:
id_auto | name | type
1, john, person
I would like to do like the following examples:
I know this is a dumb question, but a search a lot and couldn't find any answer for this. Basically, I would like to produce data sample in this example's format from my pre existing mysql tables.

Taken from the MySQL website.
https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-output-table-format.html
5.6.1 Table Format
The table format is used by default for printing result sets when MySQL Shell is in interactive mode. The results of the query are presented as a formatted table for a better view and to aid analysis.
To get this output format when running in batch mode, start MySQL Shell with the --result-format=table command line option (or its alias --table), or set the MySQL Shell configuration option resultFormat to table.
mysql-sql> select * from sakila.actor limit 3;
+----------+-------------+----------------+----------------------+
| actor_id | first_name | last_name | last_update |
+----------+-------------+----------------+----------------------+
| 1 | PENELOPE | GUINESS | 2006-02-15 4:34:33 |
| 2 | NICK | WAHLBERG | 2006-02-15 4:34:33 |
| 3 | ED | CHASE | 2006-02-15 4:34:33 |
+----------+-------------+----------------+----------------------+

Related

How to add Time series queries with grafana and MySQL?

I'm new to grafana and playing around to see if it could fit my needs for a research lab.
I'm using grafana-server Version 4.5.2 (commit: ec2b0fe)
I tried to follow the grafana documentation about mysql datasources (sorry I'm not allowed to post more than two links, just try to search in your favorite search engine...)
I have succefully added a MySQL data source.
Here is my database :
mysql> DESC meteo;
+-------------+----------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+----------+------+-----+---------+----------------+
| id | int(100) | NO | PRI | NULL | auto_increment |
| date_insert | datetime | NO | | NULL | |
| temperature | float | NO | | NULL | |
+-------------+----------+------+-----+---------+----------------+
Following the documentation I've added a panel "Table" with the following query...
SELECT
date_insert as 'Date',
temperature as 'Temperature'
FROM meteo
...and choosen "Format as Table"
The result is ok as you can see.
Grafana Panel Format Table
Now I would like to have a graph like this :
Grafana Panel Format Time series
How can I achieve this with my database ? I don't understand the doc which says :
If you set Format as to Time series, for use in Graph panel for example,
then there are some requirements for what your query returns.
Must be a column named time_sec representing a unix epoch in seconds.
Must be a column named value representing the time series value.
Must be a column named metric representing the time series name.
How can I apply this with my database ? Is it just possible ?
Here is the solution, thanks to the Grafana team !
daniellee's answer

Compare strings of text between two tables in a database or locally

Edit: SQL doesn't work for this. I just found out about Solr/Sphinx and it seems like the right tool for this problem, so if you know Solr or Sphinx I'm eager to hear from you.
Basically, I have a .tsv with patent info and a .csv with product names. I need to match each row of the patents column against the product names and extract the occurrences in a new .csv column.
You can scroll down and see the example at the end.
Original question:
SQL newbie here so bear with me :). I can't figure out how to do this:
My database:
mysql> SHOW TABLES;
+-----------------------+
| Tables_in_prodpatdb |
+-----------------------+
| assignee |
| patents |
| patent_info |
| products |
+-----------------------+
mysql> DESCRIBE patents;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| ... | | | | | |
| patent_id | varchar(20) | YES | | NULL | |
| text | text | YES | | NULL | |
| ... | | | | | |
+-------------+-------------+------+-----+---------+-------+
mysql> DESCRIBE products;
+-------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+-------+
| name | text | YES | | NULL | |
+-------------+-------------+------+-----+---------+-------+
I have to work with the columns name and text, they look like this:
name
product1
product2
product3
...
~10M rows
text
long text description 1
long text description 2
long text description 3
...
~88M rows
I need to check patents.text row 1 and match it against products.name column to find every product name in that row, then store those products names in a new table. Then check row 2 and repeat.
If a patents.text row has a product name several times only copy it to the new table once. If some row has no product names just skip it. The output should be something like this:
Operation Product
1 prod5, prod6
2 prod7
...
An example:
name
valve
a/c fan
farmed salmon
...
text
This patent deals with a new approach to air-conditioned fan. With some new valve the a/c fan is
so much better. The new valve is great.
This patent has no product names in it.
This patent talks about farmed salmon.
...
Desired output:
Operation Product
1 valve, a/c fan
2 farmed salmon
...
You can use GROUP_CONCAT with inner SELECT query, e.g.:
SELECT p.text,
(SELECT GROUP_CONCAT(name) FROM products WHERE LOCATE(LOWER(name), LOWER(p.text)) > 0) AS 'products'
FROM patent p;
The only way I can see doing this with a reasonable performance is a full text search. I've seldom done these myself (maybe 3 times in 20+ years now); so I'll defer to someone else w/ more experience.
Using https://dev.mysql.com/doc/refman/5.7/en/fulltext-search.html as a starting point.
Provided the full text index has been created, it may be something as simple as:
SELECT pat.patent_ID, group_concat(P.Name)
FROM patents pat
CROSS JOIN products p
WHERE MATCH (pat.text)
AGAINST (p.name IN NATURAL LANGUAGE MODE)
GROUP BY pat.patent_ID;
Since every product vs every patent we have to cross join so we now have 880 million rows; that alone is a a lot. The more reading I do on this however, the more I realize we're dealing with unstructured data in a RDBMS. By its nature that's not an ideal fit; and there may be much more optimized methods to handle this outside of a RDBMS, or we have to spend the time to structure the data in the RDBMS so it can be more effective with the indexes (such as splitting the text into it's own rows per word for indexing)
Lastly, do we really need to look for ALL products? the sheer size of the data involved on both sizes means this is going to take time in a database that doesn't handle unstructured data well.
Edit
Scratch the below as it will not be able to handle the load effectively. But keeping it for posterity.
I think concat() and group_concat() may do the trick.
We join where the patent.text is like the product name generating multiple rows. the group_concat then combines these rows into one record. I'm not sure where "Operation" comes from in your result.
SELECT pat.text, group_concat(P.Name) as Product
FROM patents pat
INNER JOIN text
on pat.text like concat('%',p.name,'%')
GROUP by pat.text
However don't expect this to be fast; as we're doing a wild card search using a % on both ends; so no index can be used.

Dynamic value to display numbers of entries in second table

I've got multiple entries in table A and would like to display the number of entries in a coloumn of table B. Is there a way to create a dynamic cell-content displaying the number of entries in a table?
I'm a beginner in MySQL and did not find a way to do it so far.
Example table A:
+----+------+------------+
| id | name | birthday |
+----+------+------------+
| 1 | john | 1976-11-18 |
| 2 | bill | 1983-12-21 |
| 3 | abby | 1991-03-11 |
| 4 | lynn | 1969-08-02 |
| 5 | jake | 1989-07-29 |
+----+------+------------+
What I'd like in table B:
+----+------+----------+
| id | name | numusers |
| 1 | tblA | 5 |
+----+------+----------+
In my actual database there is no incrementing ID so just taking the last value would not work - if this would've been a solution.
If MySQL can't handle this the option would be to create some kind of cronjob on my server reading the number of rows and writing them into that cell. I know how to do this - just checking if there's another way.
I'm not looking for a command to run on the mysql-console. What I'm trying to figure out is if there's some option which dynamically changes the cell's value to what I've described above.
You can create a view that will give you this information. The SQL for this view is inspired by an answer to a similar question:
CREATE VIEW table_counts AS
SELECT table_name, table_rows
FROM information_schema.tables
WHERE table_schema = '{your_db}';
The view will have the cells you speak of. As you can see, it is just a filter on an already existing table, so you might consider that this table information_schema.tables is the answer to your question.
You can do that directly with COUNT() for example SELECT COUNT(*) FROM TblA The you get all rows from that table. If you IDXs are ok then its very fast. If you write it to another table you have to make an request too to get the result of the second table. So i think your can do it directly.
If you have some performance problems there are some other possibilities like Triggers or Stored Procedures to calculate that result and save them in a memory table to get a better performance.

Reformatting MySQL table as grid

I have a table for holding translations. It is laid out as follows:
id | iso | token | content
-----------------------------------------------
1 | GB | test1 | Test translation 1 (English)
2 | GB | test2 | Test translation 2 (English)
3 | FR | test1 | Test translation 1 (French)
4 | FR | test2 | Test translation 2 (French)
// etc
For the translation management tool to go along with the table I need to output it in something more like a spreadsheet grid:
token | GB | FR | (other languages) -->
-------------------------------------------------------------------------------------------
test1 | Test translation 1 (English) | Test translation 1 (French) |
test2 | Test translation 1 (French) | Test translation 2 (French) |
(other tokens) | | |
| | | |
| | | |
V | | |
I thought this would be easy, but it turned out to be far more difficult than I expected!
After a lot of searching and digging around I did find group_concat, which for the specific case above I can get to work and generate the output I'm looking for:
select
token,
group_concat(if (iso = 'FR', content, NULL)) as 'FR',
group_concat(if (iso = 'GB', content, NULL)) as 'GB'
from
translations
group by token;
However, this is, of course, totally inflexible. It only works for the two languages I have specified so far. The instant I add a new language I have to manually update the query to take it into account.
I need a generalized version of the query above, that will be able to generate the correct table output without having to know anything about the data stored in the source table.
Some sources claim you can't easily do this in MySQL, but I'm sure it must be possible. After all, this is the sort of thing databases exist for in the first place.
Is there a way of doing this? If so, how?
Because of mysql limitations, I need to do something like this on query side and in 1 query, I would do it like this:
query:
select token, group_concat(concat(iso,'|',content)) as contents
from translations
group by token
"token";"contents"
"test1";"GB|Test translation 1 (English),FR|Test translation 1
(French),IT|Test translation 1 (Italian)" "test2";"GB|Test translation
2 (English),FR|Test translation 2 (French),IT|Test translation 2
(Italian)"
Than While I am binding rows I could split from comma to rows and split from pipe for header..
What you seek is often called a dynamic crosstab wherein you dynamically determine the columns in the output. Fundamentally, relational databases are not designed to dynamically determine the schema. The best way to achieve what you want is to use a middle-tier component to build the crosstab SQL statement similar to what you have shown and then execute that.

Disable scientific notation in MySQL command-line client?

I have a MySQL table with many numeric columns (some INT, some FLOAT). I would like to query it with the MySQL command-line client (specifically, mysql Ver 14.14 Distrib 5.1.41, for debian-linux-gnu (x86_64) using readline 6.1), like so:
SELECT * FROM table WHERE foo;
Unfortunately, if the value of any numeric field exceeds 10^6, this client displays the result in scientific notation, which makes reading the results difficult.
I could correct the problem by FORMAT-ing each of the fields in my query, but there are many of them and many tables I would like to query. Instead I'm hoping to find a client variable or flag I can set to disable scientific notation for all queries.
I have not been able to find one in the --help or the man page, nor searching Google or this site. Instead all I find are discussions of preserving/removing scientific notation when using <insert-programming-language>'s MySQL API.
Thank you for any tips.
::edit::
Here's an example table ...
mysql> desc foo;
+--------------+-------------+------+-----+-------------------+
| Field | Type | Null | Key | Default |
+--------------+-------------+------+-----+-------------------+
| date | date | NO | PRI | NULL |
| name | varchar(20) | NO | PRI | NULL |
| val | float | NO | | NULL |
| last_updated | timestamp | NO | | CURRENT_TIMESTAMP |
+--------------+-------------+------+-----+-------------------+
and some example values ...
mysql> select * from foo where date='20120207';
+------------+--------+--------------+---------------------+
| date | name | val | last_updated |
+------------+--------+--------------+---------------------+
| 2012-02-07 | A | 88779.5 | 2012-02-07 13:38:14 |
| 2012-02-07 | B | 1.00254e+06 | 2012-02-07 13:38:14 |
| 2012-02-07 | C | 78706.5 | 2012-02-07 13:38:15 |
+------------+--------+--------------+---------------------+
Now, the actual values I loaded into the third field are:
88779.5, 1002539.25, 78706.5390625
and they can be seen exactly if I manipulate the value:
mysql> select date, name, ROUND(val, 10), last_updated from foo where ...
+------------+---+--------------------+---------------------+
| 2012-02-07 | A | 88779.5000000000 | 2012-02-07 13:38:14 |
| 2012-02-07 | B | 1002539.2500000000 | 2012-02-07 13:38:14 |
| 2012-02-07 | C | 78706.5390625000 | 2012-02-07 13:38:15 |
Something in the client seems to be enforcing that I only be allowed to see six significant figures, even though there are more in the table.
If a query such as
mysql> select ROUND(*, 2) from foo ...
were possible, that would be great! Otherwise I can't really take the time to individually wrap 100 column names in "ROUND()" whenever I need to inspect some data.
Interestingly, I occasionally use a phpMyAdmin interface to browse the contents of some of these tables, and that interface also has this 6 significant figure limitation. So it's not limited to just the CLI.
Well, after reading the documentation more thoroughly, I still can't see any reason why a client would limit itself to displaying only 6 sig figs from a FLOAT (especially when the table itself is definitely storing more).
Nonetheless, an acceptable solution (for this weary user) is to change all my tables to use DECIMAL(16,4) instead of FLOAT. Unfortunately, this makes all my numbers show up with 4 decimal places (even if they're all '0'). But at least all numbers have the same width now, and my client never displays them in scientific notation or limits the number of sig figs in its output.
Wouldn't the CAST function allow you to request that the values for a certain field are returned as DECIMAL ? Not an expert and haven't tried it, but that would be the first thing I try.
I know this is old but this helped me.. I used a view..
create view foo2 as select date, name, ROUND(val, 10) val, last_updated from foo
Then just do your queries on foo2. also works in phpmyadmin