How to select sum across 100 tables? - mysql

I unfortunately have spread some data across about 100 tables, and I don't have time to reorganize it, so I am curious as to how I might do a select sum(column_name) across that many tables.
I have found examples of how to sum across 2 tables, but never an example of 100.
Anybody know how?
Addendum: Using a very large command has resulted in a "memory exhausted" error. Is there a way to do this using LIKE ?

I would say the easiest way to do this is to do lots of selects (one for each table) of the value you want to sum and just do a sum on the union of that?
Something like :
SELECT SUM(VALUE) FROM (
select 1 VALUE
UNION
select 2 VALUE
UNION
select 3 VALUE) as DATA
Of course the selects will be selecting a column from each table and not just an integer like this, but you get the idea ...

You seem fixated on LIKE, but LIKE is for WHERE clauses, not choosing tables to select from. If selecting from all the tables at once is too much for your system to handle, the obvious solution is to query each table individually and then add up the results using a perl/php/other script.

You can do something like this:
select sum(sumcol) FROM (
select sum(col) as sumcol from table1
union all
select sum(col) as sumcol from table2
union all
select sum(col) as sumcol from table3
...
union all
select sum(col) as sumcol from table100
);
This is done with much less memory consumption when you sum-up in union parts, too.

It would be a big query, but something like this would do it:
SELECT SUM(col) FROM (
SELECT col FROM table1
UNION ALL
SELECT col FROM table2
UNION ALL
SELECT col FROM table3
...
SELECT col FROM table100
) a

Related

mysql keep position of query with union statement - mysql

1. select something, date_something from my_table
where [conditions]
union
2. select something, date_something from my_table
where [conditions]
union
3. select something, date_something from my_table
where [conditions]
This pseudo-code at least in my workbench returns me the exact result I need. I didn't use the ORDER BY keyword at the end, which I always do, because applying will destroy the order obviously.
Is there a way to assure the query would return data in the following order? For me it is really important I could fix the order by 1,2,3 "partitions", rather than applying it overvalues. I hope you understand.
Any ideas would be welcomed.
You should be able to add a field to do that, e.g.:
select 1 as Partition, something, date_something
from my_table
where [conditions]
union
select 2 as Partition, something, date_something
from my_table
where [conditions]
union
select 3 as Partition, something, date_something
from my_table
where [conditions]
order by Partition

How can I create a view with duplicate columns and merge them?

I have pm_message tables with 1~9, and I want to create a view to simplified the process of MySQL query.
What I have is
CREATE VIEW `pm_messages` AS
SELECT * FROM
`pm_messages_0`,
`pm_messages_1`,
`pm_messages_2`,
`pm_messages_3`,
`pm_messages_4`,
`pm_messages_5`,
`pm_messages_6`,
`pm_messages_7`,
`pm_messages_8`,
`pm_messages_9`;
I got error with douplicate column. There is no record is duplicate, I want to merge all of them in view, what should I do?
You have coded a colossal cross join. Depending on the number of rows, it probably wouldn't return before the universe suffers entropy heat death.
I'm almost certain you want a union:
CREATE VIEW `pm_messages` AS
SELECT * FROM `pm_messages_0` union all
SELECT * FROM `pm_messages_1` union all
SELECT * FROM `pm_messages_2` union all
SELECT * FROM `pm_messages_3` union all
SELECT * FROM `pm_messages_4` union all
SELECT * FROM `pm_messages_5` union all
SELECT * FROM `pm_messages_6` union all
SELECT * FROM `pm_messages_7` union all
SELECT * FROM `pm_messages_8` union all
SELECT * FROM `pm_messages_9`;
This will work if all tables have the same number and type of columns. If not, you'll have to explicitly select columns such that each select returns the same number and type of columns.

How get items which all not present in mysql Table in a range

I have an mysql table where Ids are between 1 to 1815. but some of the Ids are not available. For example 15, 22, 55 etc..
How to get those ids??
I tried
select product_id from table_products where product_id not BETWEEN 1 and 1815
But its not working.
If it doesn't exists in table then you can hard code the values using UNION like below. Well, I had no idea about How to find gaps in sequential numbering in mysql?. Which looks really nice and probably a much better solution than what I am proposing.
select product_id
from table_products
where product_id BETWEEN 1 and 1815
UNION
select 15 as product_id from dual
UNION
select 22 as product_id from dual
UNION
select 55 as product_id from dual
I found this answer in How to find gaps in sequential numbering in mysql? and found it really does the trick (adapted for your purpose):
SELECT
CONCAT(z.expected, IF(z.got-1>z.expected, CONCAT(' thru ',z.got-1), '')) AS missing
FROM (
SELECT
#rownum:=#rownum+1 AS expected,
IF(#rownum=table_products.product_id, 0, #rownum:=table_products.product_id) AS got
FROM
(SELECT #rownum:=0) AS a
JOIN table_products
ORDER BY table_products.product_id
) AS z
WHERE z.got!=0;
Hope this does the job for you. The only thing it does not do is stop at a particular product_id, but I assume you can look at the result and take the data that you need.

MySQL select from custom set and compare with table data

Hi I'm trying to solve which elements doesn't exists in my database. In order to do so I want to compare list of integers (output from external script) with data in table. How to do such thing like:
SELECT * FROM (1,1,2,3,5,8,13...) l WHERE l NOT IN (select id from table1);
This is probably best done with a left outer join. But, your problem is creating the table of constants:
SELECT *
FROM (select 1 as id union all select 2 union all select 3 union all select 5 union all
select 8 union all select 13 union all select 21 . . .
) ids
where ids.id NOT IN (select id from table1);
This can have odd behavior, if table1.id is ever NULL. The following works more generally:
SELECT *
FROM (select 1 as id union all select 2 union all select 3 union all select 5 union all
select 8 union all select 13 union all select 21 . . .
) ids left outer join
table1 t1
on ids.id = t1.id
where t1.id is null;
EDIT:
The size of a MySQL query is dictated by the parameter max_packet_size (see here). The most recent version has a limit of 1 Gbyte. You should be able to fit 18,000 rows of:
select <n> union all
into that limit, quite easily. Gosh, I don't even think it would be 1 megabyte. I would say, though, that passing a list of 18,000 ids through the application seems inefficient. It would be nice if one database could just pull the data from the other database, without going through the application.
If your set to compare is huge I'd recommend you to create a temporary table myids with the only column id, put there all your 18K values and run query like that:
select id from myids where myids.id not in (select id from table1);

Inserting duplicate records based on a value without using cursor

I had a problem in database. I have to insert duplicate records of a particular record on a another table based on a value.
First i used cursor to fetch each records and get the number of duplication i wants and after that used another cursor for duplication. Everything worked fine. But if the records in more than 500, i went dead slow. Then i did some research and found a way to insert without cursor.
INSERT INTO report(id, Name)
SELECT i.id,i.Name FROM (SELECT 1 AS id
UNION SELECT 2
UNION SELECT 3
UNION SELECT 4
UNION SELECT 5
UNION SELECT 6
UNION SELECT 7
UNION SELECT 8
UNION SELECT 9
UNION SELECT 10) AS o
INNER JOIN table i WHERE o.id<=i.frequence;
where frequence is the number of duplication. Please drop your idea to improve your query.
You could try creating a table with a record for each value from 1 to 10 and then join to that. I'm not sure it would be any faster though. You would have to experiment with it.
In this example the table with the values from 1 to 10 is called "dup" and the field containing these values is called "id".
INSERT INTO report(id, Name)
SELECT i.id, i.Name
FROM table i
JOIN dup d
ON d.id <= i.frequence;
If you have any table that contains a row number that goes at least as high as the maximum frequence, you could to this:
INSERT INTO report(id, Name)
SELECT i.id,i.Name FROM table i
inner join (
select distinct some_row_number_column from some_table
) o on o.some_row_number_column <= i.frequence;
This is basically the same as what you were doing, but it avoids the messy union all statements.
Or you could make a cursor that inserts numbers from 1 to the maximum frequence into a temporary table, then use that in your join. Or you could use a row numbering variable to generate the necessary sequence. Basically, do anything that will generate a list of consecutive numbers from 1 to the maximum that you need.
I would normally use recursion for this (DB2 syntax):
INSERT INTO report(id, Name)
with num_list (num) as (
values (1)
union all
select num + 1 from num_list
where num < (select max(frequence) from table)
)
SELECT i.id,i.Name FROM table i
inner join num_list on num_list.num <= i.frequence;
However, MySQL doesn't support recursion, apparently.