MySQL select from tables returned by query - mysql

I am trying to select from MySQL tablenames returned by a query. The tablenames are table_prefix_date (e.g. table_prefix_20160801).
To get all the dates and corresponding tablenames I do something like this:
select concat('db_name.table_prefix_',a.Date)
from (
select date_format(curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY,'%Y%m%d') as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
where date_format(Date,'%Y-%m-%d') between '2016-08-01' and '2016-08-20'
order by 1 asc;
All the tables have the same columns and indexes. Just doing select * from (queryabove); fails.
Can somebody please give me some working example of how I can retrieve data from the tables returned by the query above?

You need to execute a dynamic SQL statement:
set #sql = (
select group_concat(replace('select * from #table', '#table',
concat('table_prefix_', date_format(a.Date, '%Y%m%d'))
) separator ' union all ')
from (select date_sub(curdate(), INTERVAL (a.a + (10 * b.a) + (100 * c.a)) day) as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) a cross join
(select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) b cross join
(select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) c
) a
where Date between '2016-08-15' and '2016-08-18'
);
prepare stmt1 from #sql;
execute stmt1;
Here is a SQL Fiddle for the above.
The query is essentially your query with the select and union all logic.
More importantly, though, you should not be designing a set of tables that contain the same information. Instead, you should have a date column in a big table that you insert into.

Related

get Mondays between two dates mysql

I want to get the Mondays between two dates with a select statement, but I only have searched in sql server.
I have tried this, but it doesn´t work:
SELECT DATE_ADD('2017-01-01', INTERVAL ROW DAY) AS Date
FROM (
SELECT #row := #row + 1 AS row
FROM (
SELECT 0 UNION ALL
SELECT 1 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6
) t1,
(
SELECT 0 UNION ALL
SELECT 1 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6
) t2,
(
SELECT #row:=-1
) t3 LIMIT 31
) b
WHERE DATE_ADD('2017-01-01', INTERVAL ROW DAY) BETWEEN '2017-01-01' AND '2017-12-31'
AND DAYOFWEEK(DATE_ADD('2017-01-01', INTERVAL ROW DAY)) = 2
This query only gives me the Monday´s date for one month.
I hope that you can help me
Regards!
If you really want to solve this SQL only, you have to delve a bit deeper and generate a sequence of days, this is by far the most difficult side task to solve this. Besides this, as you have already guessed, you can use DAYOFWEEK or WEEKDAY to get your desired days.
SELECT *
FROM (
SELECT DATE_ADD('2013-01-01',
INTERVAL n4.num*1000+n3.num*100+n2.num*10+n1.num DAY ) AS DATE
FROM (
SELECT 0 AS num
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) AS n1,
(
SELECT 0 AS num
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) AS n2,
(
SELECT 0 AS num
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) AS n3,
(
SELECT 0 AS num
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) AS n4
) AS a
WHERE DATE >= '2017-01-01' AND DATE < NOW()
AND WEEKDAY(DATE) = 0
ORDER BY DATE
Some other RDBMS have inbuild functions for that.
If would be way easier if you have a calendar table where all dates are already present.
I think that this solution will work with better performance than previous
SET #date_start = date('2019-07-06');
SET #date_end = date('2019-09-18');
SELECT CASE WHEN MOD(DAYOFWEEK(#date_start), 7) <= 2 AND
MOD(DAYOFWEEK(#date_start), 7) + DATEDIFF(v.selected_date, #date_start) - 7 * FLOOR(DATEDIFF(v.selected_date, #date_start) / 7) >= 2 OR
MOD(DAYOFWEEK(#date_start), 7) > 2 AND
MOD(DAYOFWEEK(#date_start), 7) + DATEDIFF(v.selected_date, #date_start) - 7 * FLOOR(DATEDIFF(v.selected_date, #date_start) / 7) >= 9 THEN 1 ELSE 0 END
+ FLOOR(DATEDIFF(v.selected_date, #date_start) / 7) num_of_mo
, #date_start start_date,v.selected_date end_date
FROM (select adddate(#date_start,t4*10000 + t3*1000 + t2*100 + t1*10 + t0) selected_date from
(select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
WHERE v.selected_date <= #date_end;

Generate days from date range sql

I need to generate the days between two dates in sql like this:
generate days from date range
Im using this query:
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
Works well but this generates always 1000 days. How can i generate any other number of days like 365?
You could add a limit clause (and an order by)
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all select 8 union all
select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all select 8 union all
select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all select 8 union all
select 9) as c
) a
order by 1 desc
limit 365
Or, if you are allowed to create temporary tables, in a more readable fashion - and extendable to 10,000 integers or more quite easily:
CREATE TEMPORARY TABLE units(idx)
ENGINE=MEMORY
AS (
SELECT 0
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
);
SELECT a.the_date
FROM (
SELECT curdate() - INTERVAL (hundreds + tens + units) DAY AS the_date
FROM (SELECT idx AS units FROM units) units
CROSS JOIN (SELECT idx* 10 AS tens FROM units) tens
CROSS JOIN (SELECT idx* 100 AS hundreds FROM units) hundreds
WHERE hundreds + tens + units < 365
) AS a
ORDER BY 1
;

Select all dates between two dates not using a table (generate list of dates)

Is there a way to get all dates between two dates without using any MySQL table
Something like:
SELECT date BETWEEN '2012-02-10' AND '2012-02-15'
that would result in this:
out put date list
2012-02-10
...
2012-02-15
Here is the query:
This query gives proper result in both the databases : MariaDB & MySQL.
SELECT ADDDATE('2012-02-10', INTERVAL #i:=#i+1 DAY) AS DAY
FROM (
SELECT a.a
FROM (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c
) a
JOIN (SELECT #i := -1) r1
WHERE
#i < DATEDIFF('2012-02-15', '2012-02-10')

Convert query from MySql to Sqlite

I need to convert this query from MySQL format to SQLite. I'm trying myself but I've found some difficulty.
In SQLite, the curdate() and the interval functions do not exist.
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
where a.Date between '2010-01-20' and '2010-01-24'
What this query actually does is just generating lots of consecutive dates (up to one thousand previous days).
In SQLite 3.8.3 or later, this can be done more easily with a recursive common table expression:
WITH RECURSIVE dates(d)
AS (VALUES('2010-01-20')
UNION ALL
SELECT date(d, '+1 day')
FROM dates
WHERE d < '2010-01-24')
SELECT d AS date FROM dates;
Here is the basic syntax:
select a.Date
from (select date('now', '-'||(a.a + (10 * b.a) + (100 * c.a))|| ' days') as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9
) a cross join
(select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9
) b cross join
(select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9
) c
) a;
I left out the where clause because those dates are more than 1000 days in the past, so they won't select anything anyway.

How do I add the first of the week for every week from 2011-01-02 until 2100-01-01 to a mysql table via a while loop?

I'm looking to make a date lookup table that will allow me to match some pivots together in excel and I was wondering how to go about taking the first of every week and adding it to a new mysql table?
This query selects all sundays of 2011. Expand it for the years you need and insert this select into a table of your choice.
select a.Date
from (
select DATE('2011-12-31') - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
where DAYOFWEEK(a.Date)=1 and a.Date between '2011-01-01' and '2011-12-31'
Reference