Summing all 5 table values to form new table? - mysql

I have 5 tables with following properties,
+--------------------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+-------------+------+-----+---------+-------+
| actor_id | int(11) | YES | MUL | NULL | |
| activity_object_id | int(11) | YES | MUL | NULL | |
| interest_level | tinyint(4) | YES | | 10 | |
| feed_view | smallint(6) | YES | | 0 | |
| quick_view | smallint(6) | YES | | 0 | |
| page_view | smallint(6) | YES | | 0 | |
| fullscreen_view | smallint(6) | YES | | 0 | |
| reserved1 | int(11) | YES | | NULL | |
| reserved2 | int(11) | YES | | NULL | |
| reserved3 | int(11) | YES | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+--------------------+-------------+------+-----+---------+-------+
How we can create new temporary table which is sum of all the 5 table values. activity_object_id is unique and one table might contain activity_object_id while the other one may not.
table1 has one active_object_id say 'gowthamkey', table2 has same key 'gowthamkey', and table3 might not have 'gowthamkey'. So I want to sum up all the tables values into new table, so that it has one key 'gowthamkey' where values are sum of:
feed_view,quick_view,page_view,fullscreen_view,reserved1,reserved2,reserved3 except actor_id, interest_level, created_at, updated_at.
Here is my query as per #bummer answer:
CREATE TABLE actor_activity_object_stats_temp_7_days_12 AS
select actor_id, activity_object_id, interest_level, SUM(feed_view) AS feed_view, SUM(quick_view) AS quick_view, SUM(fullscreen_view) as fullscreen_view
from (
select * from actor_activity_object_stats_temp_2016_04_29
union all,
select * from actor_activity_object_stats_temp_2016_04_30
union all,
select * from actor_activity_object_stats_temp_2016_05_01
union all,
select * from actor_activity_object_stats_temp_2016_05_02
union all,
select * from actor_activity_object_stats_temp_2016_05_03
union all,
select * from actor_activity_object_stats_temp_2016_05_04
union all,
select * from actor_activity_object_stats_temp_2016_05_05
union all,
select * from actor_activity_object_stats_temp_2016_05_06
union all,
select * from actor_activity_object_stats_temp_2016_05_07
union all,
select * from actor_activity_object_stats_temp_2016_05_08 ) AS X
group by activity_object_id

Start with a UNION, then use SUM() to add all the values from all the tables for the same activity_object_id.
CREATE TABLE new_table
AS SELECT activity_object_id, SUM(feed_view) AS feed_view, SUM(quick_view) AS quick_view, ...
FROM (SELECT * FROM table1
UNION ALL
SELECT * FROM table2
UNION ALL
SELECT * FROM table3
...) AS x
GROUP BY activity_object_id

I believe this should solve your issue.
create table new_table
as
select * from table1
union
select * from table2
union
select * from table3
union
select * from table4
union
select * from table5)
here's a sql fiddle to illustrate.

Related

MySQL: Obtain Fields From Multiple Tables Each Result Represented As A Row

I have multiple tables with this structure:
+----------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+----------+----------+------+-----+---------+-------+
| nick | char(25) | NO | PRI | NULL | |
| id | int(11) | NO | | NULL | |
| cooldown | datetime | NO | | NULL | |
+----------+----------+------+-----+---------+-------+
I would like to obtain all of the id fields from all of these tables given a nick. These tables (lets call them table1, table2, table3) may or may not be empty. What is the best way to do this in one query?
My desired output would look like:
+-------+
| id |
+-------+
| 15679 |
| 72620 |
+-------+
You need a UNION query:
SELECT id FROM table1 WHERE nick='nick'
UNION
SELECT id FROM table2 WHERE nick='nick'
UNION
SELECT id FROM table3 WHERE nick='nick'
UNION will only return unique rows, if you want your query to return duplicates you can use UNION ALL instead.
Select Id from table1 where nick=nick
UNION
Select Id from table2 where nick=nick
UNION
...
UNION
...

MySQL merge results into table from count of 2 other tables, matching ids

I've got 3 tables: model, model_views, and model_views2. In an effort to have one column per row to hold aggregated views, I've done a migration to make the model look something like this, with a new column for the views:
+---------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+---------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | NO | | NULL | |
| [...] | | | | | |
| views | int(20) | YES | | 0 | |
+---------------+---------------+------+-----+---------+----------------+
This is what the columns for model_views and model_views2 look like:
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | smallint(5) | NO | MUL | NULL | |
| model_id | smallint(5) | NO | MUL | NULL | |
| time | int(10) unsigned | NO | | NULL | |
| ip_address | varchar(16) | NO | MUL | NULL | |
+------------+------------------+------+-----+---------+----------------+
model_views and model_views2 are gargantuan, both totalling in the tens of millions of rows each. Each row is representative of one view, and this is a terrible mess for performance. So far, I've got this MySQL command to fetch a count of all the rows representing single views in both of these tables, sorted by model_id added up:
SELECT model_id, SUM(c) FROM (
SELECT model_views.model_id, COUNT(*) AS c FROM model_views
GROUP BY model_views.model_id
UNION ALL
SELECT model_views2.model_id, COUNT(*) AS c FROM model_views2
GROUP BY model_views2.model_id)
AS foo GROUP BY model_id
So that I get a nice big table with the following:
+----------+--------+
| model_id | SUM(c) |
+----------+--------+
| 1 | 1451 |
| [...] | |
+----------+--------+
What would be the safest route for pulling off commands from here on in to merge the values of SUM(c) into the column model.views, matched by the model.id to model_ids that I get out of the above SQL query? I want to only fill the rows for models that still exist - There is probably model_views referring to rows in the model table which have been deleted.
You can just use UPDATE with a JOIN on your subquery:
UPDATE model
JOIN (
SELECT model_views.model_id, COUNT(*) AS c
FROM model_views
GROUP BY model_views.model_id
UNION ALL
SELECT model_views2.model_id, COUNT(*) AS c
FROM model_views2
GROUP BY model_views2.model_id) toupdate ON model.id = toupdate.model_id
SET model.views = toupdate.c

MySQL Pivot Field Names to values in row

I'm new to pivoting, so I came here to get some advice on this. I have a table with fields benchmarkname and value. However, another table is populated differently and out of my control: it has each benchmarkname as its own field in the table, with the row value being the value. The layout is below:
Table 1
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| stream | double | YES | | NULL | |
| pisec | double | YES | | NULL | |
| iozws | double | YES | | NULL | |
| iozwb | double | YES | | NULL | |
| iozrs | double | YES | | NULL | |
| iozrb | double | YES | | NULL | |
Table 2
| BenchmarkName | varbinary(43) | YES | | NULL | |
| Value | decimal(14,0) | YES | | NULL | |
My question is: how do I convert the first table to look like second dynamically? I believe the answer lies in a pivot, but I am unsure.
I think you want to unpivot the first table. UNPIVOTing takes the data from your columns and converts it into rows. MySQL does not have unpivot so you will have to use a UNION ALL query:
select 'stream' BenchmarkName, stream value
from table1
union all
select 'pisec' BenchmarkName, pisec value
from table1
union all
select 'iozws' BenchmarkName, iozws value
from table1
union all
select 'iozwb' BenchmarkName, iozwb value
from table1
union all
select 'iozrs' BenchmarkName, iozrs value
from table1
union all
select 'iozrb' BenchmarkName, iozrb value
from table1

Join 2 select queries with 2 results into one query with one result?

What I try to accomplish is that I want to select one row from tableA and one row from tableB and combine the results (comlumn names are different).
The layout of tableA is this:
+----------------------------+--------------+------+-----+---------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------------------------+--------------+------+-----+---------------------+----------------+
| user_id | int(11) | NO | PRI | NULL | auto_increment |
| nickname | varchar(32) | NO | | NULL | |
| password | varchar(129) | NO | | NULL | |
| mafia_id | int(11) | NO | | 0 | |
+----------------------------+--------------+------+-----+---------------------+----------------+
and of tableB this:
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| mafia_id | int(11) | NO | PRI | NULL | auto_increment |
| mafia_name | varchar(32) | NO | | | |
| mafia_tag | varchar(5) | NO | | | |
| mafia_color | int(11) | NO | | 0 | |
| mafia_car | int(11) | NO | | 0 | |
| mafia_base | int(11) | NO | | 0 | |
+-------------+-------------+------+-----+---------+----------------+
I tried queries like:
SELECT *
FROM users
WHERE users.nickname = 'Gamer_Z'
UNION
SELECT * FROM mafia
WHERE mafia.mafia_id = (
SELECT users.mafia_id
FROM users
WHERE users.nickname = 'Gamer_Z'
);
and this:
SELECT *
FROM users
WHERE nickname = 'Gamer_Z'
INNER JOIN mafia ON mafia.mafia_id = users.mafia_id;
But those queries give errors, I tried several others but these ones look, well, good?
I read these questions too:
How can I join two tables with different number of rows in MySQL?
Combine Multiple Query Results in MySQL (by column)
But I can't seem to fix my problem.
The output format I would like is this:
|users.user_id|users.nickname|users.password|users.mafia_id|mafia.mafia_name|mafia.mafia_tag|mafia.mafia_color|mafia.mafia_car|mafia.mafia_base|
How can I build the correct query for what I try to accomplish in MySQL(5)?
Thanks in advance!
\EDIT::
I almost forgot one thing! IF the mafia_id doesn't exists in tableB then there stil has to be the tableA row retured. (so the user is not in a mafia, I just load the default user data)
You have to put the WHERE condition after the JOIN, not before it:
SELECT *
FROM users a
LEFT JOIN mafia b ON a.mafia_id = b.mafia_id
WHERE a.nickname = 'Gamer_Z'
the join is wrong
should be
SELECT *
FROM users a
JOIN mafia b ON a.mafia_id = b.mafia_id and a.nickname = 'Gamer_Z'

Optimize SQL query (Facebook-like application)

My application is similar to Facebook, and I'm trying to optimize the query that get user records. The user records are that he as src ou dst. The src is in usermuralentry directly, the dst list are in usermuralentry_user.
So, a entry can have one src and many dst.
I have those tables:
mysql> desc usermuralentry ;
+-----------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+------------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_src_id | int(11) | NO | MUL | NULL | |
| private | tinyint(1) | NO | | NULL | |
| content | longtext | NO | | NULL | |
| date | datetime | NO | | NULL | |
| last_update | datetime | NO | | NULL | |
+-----------------+------------------+------+-----+---------+----------------+
10 rows in set (0.10 sec)
mysql> desc usermuralentry_user ;
+-------------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| usermuralentry_id | int(11) | NO | MUL | NULL | |
| userinfo_id | int(11) | NO | MUL | NULL | |
+-------------------+---------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
And the following query to retrieve information from two users.
mysql> explain
SELECT *
FROM usermuralentry AS a
, usermuralentry_user AS b
WHERE a.user_src_id IN ( 1, 2 )
OR
(
a.id = b.usermuralentry_id
AND b.userinfo_id IN ( 1, 2 )
);
+----+-------------+-------+------+-------------------------------------------------------------------------------------------+------+---------+------+---------+------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------------------------------------------------------------------------------+------+---------+------+---------+------------------------------------------------+
| 1 | SIMPLE | b | ALL | usermuralentry_id,usermuralentry_user_bcd7114e,usermuralentry_user_6b192ca7 | NULL | NULL | NULL | 147188 | |
| 1 | SIMPLE | a | ALL | PRIMARY | NULL | NULL | NULL | 1371289 | Range checked for each record (index map: 0x1) |
+----+-------------+-------+------+-------------------------------------------------------------------------------------------+------+---------+------+---------+------------------------------------------------+
2 rows in set (0.00 sec)
but it is taking A LOT of time...
Some tips to optimize? Can the table schema be better in my application?
Use this query
SELECT *
FROM usermuralentry AS a
left join usermuralentry_user AS b
on b.usermuralentry_id = a.id
WHERE a.user_src_id IN(1, 2)
OR (a.id = b.usermuralentry_id
AND b.userinfo_id IN(1, 2));
And for some tips here are
You are using two tables in from clause which is a cartision product and will take a lot of time as well as undesired results. Always use joins in this situation.
I think your join isn't properly formed, and you need to change the query to use UNION. The OR condition in the where clause is killing performance as well:
SELECT *
FROM usermuralentry AS a
JOIN usermuralentry_user AS b ON a.id = b.usermuralentry_id /* use explicit JOIN! */
WHERE a.user_src_id IN (1 , 2)
UNION
SELECT *
FROM usermuralentry AS a
JOIN usermuralentry_user AS b ON a.id = b.usermuralentry_id
WHERE b.usermuralentry_id IN ( 1, 2 )
You also need an index: ALTER TABLE usermuralentry_user ADD INDEX (usermuralentry_id)