Automatically inserting additional columns in MySQL 8.0 [duplicate] - mysql

This question already has an answer here:
MySQL pivot row into dynamic number of columns
(1 answer)
Closed 3 years ago.
Say I have a table like so
+----+----------+------+
| id | name | type |
+----+----------+------+
| 1 | apple | F |
| 1 | pear | F |
| 1 | cucumber | V |
| 2 | orange | F |
| 2 | grass | NULL |
| 2 | broccoli | V |
| 3 | flower | NULL |
| 3 | tomato | NULL |
+----+----------+------+
I want to end up with a table that counts the number of elements for each type (including NULL types) AND for each id, like this:
+----+-----------------+--------------+--------------+
| id | type_NULL_count | type_F_count | type_V_count |
+----+-----------------+--------------+--------------+
| 1 | 0 | 2 | 1 |
| 2 | 1 | 1 | 1 |
| 3 | 2 | 0 | 0 |
+----+-----------------+--------------+--------------+
This is rather easy to do, but is there a way (a query I can write or something else) such that when I go back and edit one of the type fields in the first table, I end up with a properly updated count table?
For example, let's say I want to add a new type (type X) and change the type field for flower from NULL to X. Is there a way to end up with the following table without having to rewrite the query or add more statements?
+----+-----------------+--------------+--------------+--------------+
| id | type_NULL_count | type_F_count | type_V_count | type_X_count |
+----+-----------------+--------------+--------------+--------------+
| 1 | 0 | 2 | 1 | 0 |
| 2 | 1 | 1 | 1 | 0 |
| 3 | 1 | 0 | 0 | 1 |
+----+-----------------+--------------+--------------+--------------+
I'm not sure if this is the best way to do this, so I am open to suggestions

Having a secondary table which it's number of columns changes based on your first table is not a viable option.
Do you need to keep the result in a table or it will be displayed as a report?
I think a better way to do this is using the SQL below calculate counts by id plus type and display using your data display tool the way you like it.
select id, type, count(*) count
from d
group by 1,2
order by 1,2
The output would be
id type count
1 F 2
1 V 1
2 F 1
2 V 1
2 1
3 X 1
3 1

Related

How to seperate an enum-value column to each value a bool column in MySQL [duplicate]

This question already has answers here:
MySQL: Pivot + Counting
(3 answers)
Closed 7 months ago.
I have a table:
+-----------+----------+
| articleId | category |
+-----------+----------+
| 1 | life |
| 1 | game |
| 2 | tech |
| 3 | life |
| ... | ... |
+-----------+----------+
Now I have to downgrade the paradigms of data, make them be flat and wide. Because they will be fed into an analysis enviroment which has no such data relationships. (actually, it's Elasticsearch)
Finally the selected data must be like this:
+-----------+------+------+------+
| articleId | game | life | tech |
+-----------+------+------+------+
| 1 | 1 | 1 | 0 |
| 2 | 0 | 0 | 1 |
| 3 | 0 | 1 | 0 |
| ... | | | |
+-----------+------+------+------+
Could you tell me how I can do that?
The categories field is enumrable, I can manually create each column.
You need to GROUP BY your articleId and check if your data exists:
SELECT t.`articleId`,
SUM(t.`category`='game') game,
SUM(t.`category`='life') life,
SUM(t.`category`='tech') tech
FROM test_test t
GROUP BY t.`articleId`
t.category='someText' will either return you 0 or 1 and then using SUM will give you your desired result.

Does Cross Join not work between two different tables with same column name?

As written on the title, does CROSS JOIN not work for different tables with the same column name?
For example,
I have one table named Fruits:
| name | price |
| apple | 1 |
| banana | 2 |
and another table named Snacks:
| name | price |
| chips | 3 |
| cookies | 4 |
Then does
SELECT Fruits.price, Snacks.price FROM Fruits CROSS JOIN Snacks
does not work properly?
I am working on a same issue, but the result shows like:
| price | price |
| 3 | 3 |
| 4 | 4 |
| 3 | 3 |
| 4 | 4 |
But what I expect is:
| price | price |
| 1 | 3 |
| 1 | 4 |
| 2 | 3 |
| 2 | 4 |
As I mentioned in the comment, it is not possible. Either your tables values are different or your query.
Check this dbfiddle showing the result value same as your expected values.
In MySQL CROSS JOIN works as expected:
price price
------ -----
1 3
2 3
1 4
2 4
See running example at DB Fiddle.

SQL - Aggregate all EXCEPT group

Consider the following sample table from a soccer tournament (let's call this table matches)
+----------+---------+--------------+
| match_id | club_id | goals_scored |
+----------+---------+--------------+
| 1 | 1 | 1 |
| 1 | 2 | 0 |
| 2 | 1 | 1 |
| 2 | 3 | 1 |
| 3 | 1 | 0 |
| 3 | 4 | 2 |
| 4 | 2 | 2 |
| 4 | 3 | 4 |
| 5 | 2 | 4 |
| 5 | 4 | 0 |
| 6 | 3 | 1 |
| 6 | 4 | 1 |
+----------+---------+--------------+
The resulting table we want should give us each club's total goals scored AND goals conceded:
+---------+--------------+----------------+
| club_id | goals_scored | goals_conceded |
+---------+--------------+----------------+
| 1 | 2 | 4 |
| 2 | 6 | 4 |
| 3 | 6 | 4 |
| 4 | 3 | 5 |
+---------+--------------+----------------+
Getting goals scored is straight forward enough...
SELECT SUM(goals_scored),
club_id
FROM matches
GROUP BY club_id
but I am absolutely flummoxed as to how to get it for each team's opponents.
I could, of course, construct a pretty complex array of subqueries to get there. If this were application-side work I'd likely just stuff it in a loop and iterate over each club to get there, but my use case requires a SQL answer if possible. Any thoughts?
edit: also if anyone has any better ideas on how to title this question, I'm all ears - I'm not really sure exactly how to describe this problem in the first place.
We can use a self-join approach here:
SELECT
m1.club_id,
SUM(m1.goals_scored) AS goals_scored,
SUM(m2.goals_scored) AS goals_conceded
FROM matches m1
INNER JOIN matches m2
ON m2.match_id = m1.match_id AND
m2.club_id <> m1.club_id
GROUP BY
m1.club_id
ORDER BY
m1.club_id;
This approach brings the goals conceded by each club to the other club, for each match, into a single row. We then just aggregate by club to get the two sums.

How to generate (join) table field using existing string field as source?

Is it possible to generate (join) a new field by combining existing fields as source ?
I have a table like this:
id | title | parent_id | path
1 | a | 0 | 1
2 | b | 1 | 1/2
3 | c | 1 | 1/3
4 | d | 3 | 1/3/4
I want to use the "path" field's string (numbers) as a kind of index and generate (join) a new field using titles insead ids like:
id | title | parent_id | path | title_path
1 | a | 0 | 1 | a
2 | b | 1 | 1/2 | a/b
3 | c | 1 | 1/3 | a/c
4 | d | 3 | 1/3/4| a/c/d
Is this possible using sql on itself or should I use php for this?

sql more than one keys in one field

I guess, the name of the question is strange, but I don't know how to state it correctly, so I'll try to describe the problem. Say, we have two tables:
1)
id | unit_name | strength | health
1 | private | 10 | 10
2 | general | 5 | 5
n | someone | 123 | 321
2)
id | rules | who_has_this_rule
1 | rule1 | 1
2 | rule2 | 2
3 | rule3 | 1
4 | rule4 | 1
The field "who_has_this_rule" correspondes with id of the first table.
But I can't figure out what to do if a unit should have more than one rule in his profile. For example, private should have rule1 and rule4. How to do this?
What you need is a join table.
A third table to join rule and units
unit_rules
id | unit_id | rule_id
1 | 1 | 1
2 | 1 | 4
3 | 2 | 1
You can have a primary key(id) or compound key(unit_id and rule_id)