Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MySQL: Is it possible to 'fill' a SELECT with values without a table?

Tags:

date

select

mysql

I need to display the total of 'orders' for each year and month. But for some months there is no data, but I DO want to display that month (with a total value of zero). I could make a helpertable 'months' with 12 records for each year, but is there maybe a way to get a range of months, without introducing a new table?

Something like:

SELECT [all year-month combinations between january 2000 and march 2011] 
FROM DUAL AS years_months

Does anybody have an idea how to do this? Can you use SELECT with some kind of formula, to 'create' data on the fly?!

UPDATE:

Found this myself: generate days from date range

The accepted answer in this question is kind of what I'm looking for. Maybe not the easiest method, but it does what I want: fill a select with data, based on a formula....

To 'create' a table on the fly with all months of the last 10 years:

SELECT CONCAT(MONTHNAME(datetime), ' ' , YEAR(datetime)) AS YearMonth,
       MONTH(datetime) AS Month,
       YEAR(datetime) AS Year 
FROM (
    select (curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) MONTH) as datetime
    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
    LIMIT 120
) AS t
ORDER BY datetime ASC 

I must admit, this is VERY exotic, but it DOES work...

I can use this select to join it with my 'orders'-table and get the totals for each month, even when there is no data in a certain month.

But using a 'numbers' or 'calendar' table is probably the best option, so I'm going to use that.

like image 657
Dylan Avatar asked Mar 26 '11 13:03

Dylan


People also ask

Can I use SELECT without from?

Although the SQL standard doesn't allow a SELECT statement without a FROM clause, pretty much every other database does support the construct of selecting and expression without a FROM clause.

How do you SELECT all records from one table that do not exist in another table in MySQL?

How to Select All Records from One Table That Do Not Exist in Another Table in SQL? We can get the records in one table that doesn't exist in another table by using NOT IN or NOT EXISTS with the subqueries including the other table in the subqueries.


2 Answers

If at all possible, try to stay away from generating data on the fly. It makes very simple queries ridiculusly complex, but above all: it confuses the optimizer to no end.

If you need a series of integers, use a static table of integers. If you need a series of dates, months or whatever, use a calendar table. Unless you are dealing with some truly extraordinary requirements, a static table is the way to go.

I gave an example on how to create a table of numbers and a minimal calendar table(only dates) in this answer.

If you have those tables in place, it becomes easy to solve your query.

  1. Aggregate the order data to MONTH.
  2. Right join to the table of months (or distinct MONTH from the table of dates)
like image 54
Ronnis Avatar answered Oct 11 '22 12:10

Ronnis


You could try something like this

select * from 
    (select 2000 as year union
     select 2001 as year union
     select 2009
    ) as years, 
    (select 1 as month union 
     select 2 as month union 
     select 3 as month union 
     select 4 as month union 
     select 5 as month union 
     select 6 as month union 
     select 7 as month union 
     select 8 as month union 
     select 9 as month
     )
    AS months 
    WHERE year between 2001 AND 2008 OR (year=2000 and month>0) OR (year = 2009 AND month < 4) 
    ORDER by year,month
like image 28
johnlemon Avatar answered Oct 11 '22 12:10

johnlemon