Recursive select Mysql - mysql

I have one table with example data:
+----+---------+
| id | rede_id |
+----+---------+
| 1 | 0 |
| 2 | 38 |
| 3 | 1 |
| 38 | 1 |
| 40 | 1 |
| 41 | 38 |
| 42 | 38 |
| 43 | 40 |
rede_id means what id some person belongs to. Its a network system.
For example, if I need to check network of id=1, the results needs to be like:
+----+---------+
| id | rede_id |
+----+---------+
| 3 | 1 |
| 38 | 1 |
| 40 | 1 |
| 41 | 38 |
| 42 | 38 |
| 40 | 1 |
And if rede_id of someone is '41' or '42' needs to be on results to. Goes to infinite.
I can have N rede_id with my id, N rede_id with some id that belongs to me and infinite... I need to get all results.
I don't know how to do that... Sincerely no I ideia.

MySQL 8.0 now supports recursive queries, documented here: https://dev.mysql.com/doc/refman/8.0/en/with.html#common-table-expressions-recursive
Before MySQL 8.0, there's no easy solution for querying this type of data.
There are alternative ways of storing the data, to make it easier to query.
See also:
What is the most efficient/elegant way to parse a flat table into a tree?
https://www.slideshare.net/billkarwin/models-for-hierarchical-data

Related

How to get row with max dot product using MemSQL

First of all, I'll preface this by saying I have minimal experience with SQL.
Anyways, I have a table in MemSQL of the following format:
+-----+--------+----------+----------+
| id | uuid | identity | template |
+-----+--------+----------+----------+
| int | string | string | blob |
+-----+--------+----------+----------+
I am trying to use the MemSQL DOT_PRODUCT feature to obtain the identity of the template which generates the maximum dot product against a probe vector that I have provided. Note template is a normalized array of floats of fixed length.
My SQL statement is as follows:
SELECT id, identity, MAX(DOT_PRODUCT(template, JSON_ARRAY_PACK('[<probe template here>]')))
AS score FROM collection;
However, I seem to be experiencing strange behavior, where I am getting inconsistent results (1 out of 10 times that I execute the query I will get a different identity but always the same max score). Additionally, the identity is incorrect (see further below).
The result from the query is the following (9 out of 10 times):
+----+-------------+------------------+
| id | identity | score |
+----+-------------+------------------+
| 7 | armstrong_2 | 0.56488848850131 |
+----+-------------+------------------+
As a sanity check, I wrote the following SQL statement, expecting for the max to be the same. Note, I am using the exact same probe vector from before:
SELECT id, identity, DOT_PRODUCT(template, JSON_ARRAY_PACK('[<same probe template from before>]'))
AS score FROM collection ORDER BY score DESC;
The results are as follows:
+----+--------------+--------------------+
| id | identity | score |
+----+--------------+--------------------+
| 1 | armstrong_1 | 0.56488848850131 |
| 21 | armstrong_1 | 0.56488848850131 |
| 6 | armstrong_1 | 0.56488848850131 |
| 11 | armstrong_1 | 0.56488848850131 |
| 16 | armstrong_1 | 0.56488848850131 |
| 17 | armstrong_2 | 0.534708674997091 |
| 7 | armstrong_2 | 0.534708674997091 |
| 22 | armstrong_2 | 0.534708674997091 |
| 2 | armstrong_2 | 0.534708674997091 |
| 12 | armstrong_2 | 0.534708674997091 |
| 10 | mr_bean_2 | 0.072085081599653 |
| 15 | mr_bean_2 | 0.072085081599653 |
| 5 | mr_bean_2 | 0.072085081599653 |
| 20 | mr_bean_2 | 0.072085081599653 |
| 25 | mr_bean_2 | 0.072085081599653 |
| 14 | mr_bean | 0.037121964152902 |
| 9 | mr_bean | 0.037121964152902 |
| 4 | mr_bean | 0.037121964152902 |
| 19 | mr_bean | 0.037121964152902 |
| 24 | mr_bean | 0.037121964152902 |
| 13 | jimmy_carter | -0.011749440804124 |
| 23 | jimmy_carter | -0.011749440804124 |
| 18 | jimmy_carter | -0.011749440804124 |
| 8 | jimmy_carter | -0.011749440804124 |
| 3 | jimmy_carter | -0.011749440804124 |
+----+--------------+--------------------+
What is going on? Why is the MAX identity from the first query not the same as the max identity (top row) for the second query? Is one / both of my query statements incorrect?
Additionally, when I compute the dot product by hand (without any SQL or MemSQL), I find that armstrong_1 does indeed produce the highest score of 0.56488848850131. So why is my first SQL query (with the MAX operator) not working?
This is simply not valid SQL:
SELECT id, identity, MAX(DOT_PRODUCT(template, JSON_ARRAY_PACK('[<probe template here>]'))) AS score
FROM collection;
You have no GROUP BY but the query is an aggregation function (due to the MAX(). Then there are two other columns. This is not valid SQL and it is sad that some databases allow it.
The best approach is ORDER BY:
SELECT id, identity, DOT_PRODUCT(template, JSON_ARRAY_PACK('[<probe template here>]')) AS score
FROM collection
ORDER BY score DESC
LIMIT 1; -- or whatever your database uses to limit to one row

Precalculate numbers of records for each possible combination

I have a mySQL database table containing cellphones information like this:
ID Brand Model Price Type Size
==== ===== ===== ===== ====== ====
1 Apple A71 3128 A 40
2 Samsung B7C 3128 B 20
3 Apple ZX5 3128 A 30
4 Huawei Q32 2574 B 40
5 Apple A21 2574 A 25
6 Apple A71 3369 A 30
7 Samsung A71 7413 C 40
Now I want to create another table, that would contain counts for every possible combination of the parameters.
Params Count
============================================== =======
ALL 1000000
Brand(Apple) 20000
Brand(Apple,Samsung) 40000
Brand(Apple),Model(A71) 7100
Brand(Apple),Type(A) 6000
Brand(Apple),Model(A71,B7C),Type(A,B) 7
Model(A71) 12514
Model(A71,B7C) 26584
Model(A71),Type(A) 6521
Model(A71),Type(A,B) 8958
Model(A71),Type(A,B),Size(40) 85
And so on for every possible combination. I was thinking about creating a stored procedure (that i would execute periodically), that would perform queries with every existing condition like that, but I am a little stuck on how exactly should it look like. Or is there a better way how to do this?
Edit: the reason why I want to store information like this is to be able to show number of results in filter in client application, like in the picture.
I would like to create index on the Params column to be able to get the Count number for given hash instantly, improving performance.
I also tried querying and caching the values dynamically, but I want to try this approach as well, so I can compare which one is more effective.
This is how I am calculating the counts now:
SELECT COUNT(*) FROM products;
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple');
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple', 'Samsung');
SELECT COUNT(*) FROM products WHERE Brand IN ('Apple') AND Model IN ('A71');
etc.
You can use a ROLLUP for this.
SELECT
model, type, size, COUNT(*)
FROM mytab
GROUP BY 1, 2, 3
WITH ROLLUP
With your sample data, we get the following:
| model | type | size | COUNT(*) |
| ----- | ---- | ---- | -------- |
| A21 | A | 25 | 1 |
| A21 | A | | 1 |
| A21 | | | 1 |
| A71 | A | 30 | 1 |
| A71 | A | 40 | 1 |
| A71 | A | | 2 |
| A71 | C | 40 | 1 |
| A71 | C | | 1 |
| A71 | | | 3 |
| B7C | B | 20 | 1 |
| B7C | B | | 1 |
| B7C | | | 1 |
| Q32 | B | 40 | 1 |
| Q32 | B | | 1 |
| Q32 | | | 1 |
| ZX5 | A | 30 | 1 |
| ZX5 | A | | 1 |
| ZX5 | | | 1 |
| | | | 7 |
The subtotals are present in the rows with null values in different columns, and the total is the last row where all group by columns are null.

MYSQL Insert into table's column based on column name

For some reason I am having difficulty wording this question but I will try my best. I've been searching for 2 days on and off now and haven't found a good solution to the issue.
I have a Table called InventoryNode;
_________________________________________________
| InvID | ID | Slot | ItemID1 | ItemID2 | ItemID3 |
|-------|----|------|---------|---------|---------|
| 1 | 1 | Neck | 10 | 22 | 66 |
| 1 | 2 | Head | 26 | 23 | 56 |
| 1 | 3 | Leg | 19 | 21 | 76 |
And another table called Inventory which stores the Node ID in each column
_____________________________
| ID| Neck | Head | Leg | ... |
|---|------|------|-----|-----|
| 1 | 1 | 2 | 3 | 66 |
If there a way I can insert the node ID's into the Inventory table based off the InvID and populate all the columns with the correct name with the Node's ID?
Something like this?
INSERT INTO Inventory INNER JOIN InventoryNode ON
(Inventory.ID = InventoryNode.InvID) WHERE Inventory.column_name =
InventoryNode.Slot SET InventoryNode.InvID

Is it possible to create calculation rows from query results in MySQL?

I am trying to find a way to output a calculation row (or two) of an SQL search query, so I may see the raw results along with a calculation associated to them, either above or under the listing of raw results. For instance, I have the following data:
mysql> select * from data [where condition];
+----+--------+-----+--------+
| id | height | age | weight |
+----+--------+-----+--------+
| 1 | 65.2 | 45 | 45.23 |
| 2 | 63.1 | 47 | 0 |
| 3 | 59.2 | 37 | 38.1 |
| 4 | 59.8 | 39 | 36.4 |
| 5 | 63.4 | 37 | 38.1 |
| 6 | 72.1 | 34 | 2 |
| 7 | 100 | 50 | 20 |
+----+--------+-----+--------+
And what I want is to be able to perform any query to get all or a subset of this data, but have the resulting table give something like the following (with the summary/calculation output separate from the raw data, such as either above or below it):
mysql> query???
+--------+--------+------+--------+
| id | height | age | weight |
+--------+--------+------+--------+
| 1 | 65.2 | 45 | 45.23 |
| 2 | 63.1 | 47 | 0 |
| 3 | 59.2 | 37 | 38.1 |
| 4 | 59.8 | 39 | 36.4 |
| 5 | 63.4 | 37 | 38.1 |
| 6 | 72.1 | 34 | 2 |
| 7 | 100 | 50 | 20 |
+--------+--------+------+--------+
| STDDEV | 13.26 | 5.57 | 17.15 |
| COUNT | 7 | 7 | 7 |
| etc. | etc. | etc. | etc. |
+--------+--------+------+--------+
I've found some approaches such as this (http://www.sqlservercurry.com/2011/06/sql-server-row-summary-column-summary.html) that somewhat do it, but because the calculation acts on all rows it doesn't work well for some calculations (for instance, using stddev results in "0" for everything except the calculation row).
I can create a separate result of calculations such as the following, but it would be nice to have them somehow combined, such as shown above. In addition, the following only outputs one row of calculations, and it would be nice to have several rows of pertinent calculations.
select stddev(height), stddev(age), stddev(weight) from data [where condition];
The point here is to perform any search query and get an auto-generated preview of basic descriptive information from the results (deviations, counts, mean, etc.). Hopefully this can be done directly in SQL, without needing to use another language/API.
Combine your results with union. If you need the results in a particular order, then create a column containing the precedence and order by that column.
select id, height, age, weight, 0 sortorder
from data [where condition]
union all
select 'stdev count', stddev(height), stddev(age), stddev(weight), 1
from data [where condition]
order by sortorder

Percentages in MySQL - Between two columns in the same table

I have a MySQL Table that looks like this:
Name | Pass | Fail | Pass Percent | Fail Percent
Abdy | 20 | 5 | |
Bob | 10 | 5 | |
Cantona | 40 | 10 | |
Dave | 30 | 20 | |
I am trying to get the percentages:
like : passpercent = (pass/pass+fail)*100
Can I fill the table with a single MySQL code for both the columns??
The Table would look like this hopefully:
Name | Pass | Fail | Pass Percent | Fail Percent
Abdy | 20 | 5 | 80 | 20
Bob | 10 | 5 | 66 | 33
Cantona | 40 | 10 | 80 | 20
Dave | 30 | 20 | 60 | 40
That's absolutely possible.
To fill the second table:
UPDATE mytable SET pass_pct=(pass/pass+fail)*100,fail_pct=(fail/pass+fail)*100
Granted, you could also generate those during selection of the first table (if you don't want to store the results), like:
SELECT name,pass,fail,(pass/pass+fail)*100 as pass_pct,(fail/pass+fail)*100 as fail_pct FROM mytable