× The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.



On 29-Sep-2016 13:04 -0500, James H. H. Lampert wrote:
We have the following SQL query, that works very well:

select year
, month
, sum(sales) as sales
from foo
where (year * 100 + month) >
( (year(current_date) -1) * 100 + month(current_date) )
group by year, month
order by year, month

The following query I expect [untested] is the /same/ for effect, but generates a true-temporary calendar-table to which the existing data can be joined, and then selection performed without use of derived expressions for the column data; each of the result columns of the CTE could be cast to the type\size of the respective column compared in the equal-predicates of the join [presuming that might allow for even better performance; for lack of any DDL given, I could not include that casting in my example, and for lack of any sample data, I did not spend any time testing anything but the results from the derived table(s)]:

with
py1 ( dt, yr , mo ) as
( values( date (current_date - 1 years + 1 month)
, year (current_date - 1 years + 1 month)
, month(current_date - 1 years + 1 month)
)
union all
select date ( dt + 1 month )
, year ( dt + 1 month )
, month( dt + 1 month )
from py1
where dt < current_date
)
select year
, month
, sum(sales) as sales
from foo
join py1
on year = yr
and month = mo
group by year, month
order by year, month

Of course the derived table expression [i.e. the Common Table Expression (CTE) used] as table-reference PY1 for the prior twelve MONTH values up to the present, could have that same data derived instead, from a persistent\permanent calendar-table.


But now, we want to add a fourth column, for the previous year's
sales.

Consider also, the possibility of a union of the data; i.e, the same columns, but combining the result sets from each year as rows, instead of combined as another column of the aggregated values.

Now, I can get this by itself (I think) with something like
this:

select year+1 as year
, month
, sum(sales) as py_sales
from foo
where (year * 100 + month) >
( (year(current_date) -2) * 100 + month(current_date) )
and (year * 100 + month) <=
( (year(current_date) -1) * 100 + month(current_date) )
group by year, month
order by year, month

But how would I combine these to get both the "sales" and "py_sales"
columns? Some kind of a join, maybe? But what would the syntax be?


Neither of the following was tested, but the first is much the same as what was offered by Charles, from the prior month's archive [http://archive.midrange.com/midrange-l/201609/msg00855.html], but with the aforementioned CTE as calendar-table results, to allow for a JOIN and the simplified selection predicates:

with
py1 ( dt, yr , mo ) as
( values( date (current_date - 1 years + 1 month)
, year (current_date - 1 years + 1 month)
, month(current_date - 1 years + 1 month)
)
union all
select date ( dt + 1 month )
, year ( dt + 1 month )
, month( dt + 1 month )
from py1
where dt < current_date
)
, py2 ( dt, yr, mo ) as
( select date ( dt - 1 year )
, year ( dt - 1 year )
, month( dt - 1 year )
from py1
)
select ty.month
, /* ty.year, */ ty.sales as "sales past 12 mos"
, /* py.year, */ py.sales as "sales prior 12 mos"
from table
( select year
, month
, sum(sales) as sales
from foo
join py1
on year = yr
and month = mo
group by year, month
) as ty /* This past Year */
join table
( select year
, month
, sum(sales) as sales
from foo
join py2
on year = yr
and month = mo
group by year, month
) as py /* Prior Year to this past year */
order by 1

Or as UNION of the data:

with
py1 ( dt, yr , mo ) as
( values( date (current_date - 1 years + 1 month)
, year (current_date - 1 years + 1 month)
, month(current_date - 1 years + 1 month)
)
union all
select date ( dt + 1 month )
, year ( dt + 1 month )
, month( dt + 1 month )
from py1
where dt < current_date
)
, py2 ( dt, yr, mo ) as
( select date ( dt - 1 year )
, year ( dt - 1 year )
, month( dt - 1 year )
from py1
)
( select year
, month
, sum(sales) as sales
from foo
join py1
on year = yr
and month = mo
group by year, month
)
UNION ALL
( select year
, month
, sum(sales) as sales
from foo
join py2
on year = yr
and month = mo
group by year, month
)
order by 1, 2



As an Amazon Associate we earn from qualifying purchases.

This thread ...


Follow On AppleNews
Return to Archive home page | Return to MIDRANGE.COM home page

This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].

Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.