How can I create a YearMonths table from a Years table? - sql

I have a YearMonths table where ever year requires 12 entries, one for each month, i.e.,
Year Month
2013 1
2013 2
...
2013 12
For each new year, I have to generate 12 new records. I know I can do this with a loop, but I'm trying to figure out a way to do it without one. I want to fill the table by selecting all of the years from a Years table and going from there, I'm just not sure how without using a loop.

Assuming that your YEARS table is something like this:
CREATE TABLE YEARS(Year INT)
And your YearMonths table is something like this:
CREATE TABLE YearMonths(Year INT, Month Int)
You can do something like this:
WITH CTE AS (
SELECT 1 AS Mnth
UNION ALL
SELECT Mnth + 1 FROM CTE
WHERE Mnth < 12)
INSERT INTO YearMonths (Year, Month)
SELECT Year, Mnth FROM YEARS CROSS APPLY CTE
ORDER BY Year, Mnth
This approach uses a recursive Common Table Expression (available since SQL Server 2005) to build list of integer 1-12 and then cross applies it to Years table to build final list.
Demo: http://sqlfiddle.com/#!3/bbb0f/1

Related

How to create dynamic column based on distance from specific date?

I would like to create dynamic column in Redshift, which will add new value incremented by 1 dynamically. Basically it will calculate month distance from specific date, let's say 1 Jan 2020. So for current month it should be 23, in next month it should be 24 etc. Is it possible to somehow replace something which I have now static in WITH statement? Counter stops on 12 and I would have to increment it every month manually.
with months as (
select 1 as mon union all select 2 union all select 3 union all select 4 union all
select 5 as mon union all select 6 union all select 7 union all select 8 union all
select 9 as mon union all select 10 union all select 11 union all select 12
),
I think you should use DATEDIFF function as it gives you the difference in months between two dates. Simply put the dates you want: https://docs.aws.amazon.com/redshift/latest/dg/r_DATEDIFF_function.html
Example:
select datediff(mon,'2020-01-01',current_date) as mon_diff
Depends on the size for your table, maybe save the code as a view so every time you run it you will get the correct difference.
Try this
Alter table tablename
Add New_column number Default
datediff(mon,date_col, current_date);
Or
With data as
(Select row_number() over (order by 1) rn from
table)
Select datediff(month, max(rn), current_date)
from data;
Note: replace table to some table with entries count as more than your required like 9 and so on then can limit the results as required

How to select every year from a particular year to the current year as different rows?

Say my start year is 2000 and I would like to have a one column select return every year from 2000 to the current year, example:
2000
2001
...
2012
2013
This is to populate a parameter in Reporting Services.
The easiest thing for you to do would be to create a numbers table that you would use for these types of queries.
You could also use a recursive Common Table Expression to generate the list of years:
;with cte (yr) as
(
select 2000
union all
select yr + 1
from cte
where yr+1 <=2013
)
select yr
from cte;
See SQL Fiddle with Demo

How select unique years from table

I have rows in a table in SQL Server 2008
Tell me please how select only unique years from table?
P.S.: in this table unique year is 2013
Use the YEAR function, with DISTINCT like this:
SELECT DISTINCT YEAR([date])
FROM Tablename;
SQL Fiddle Demo
This will give you:
| YEAR |
--------
| 2013 |
To use the order by clause, give it an alias and order by this alias not the original name like this:
SELECT DISTINCT YEAR([date]) AS Year
FROM Tablename
ORDER By Year;

How do I find the longest time period without gaps in SQL? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
SQL: finding longest date gap
I've got a table of below structure:
| LearnerId | FirstName | LastName | EnrollmentDate | CompletionDate |
I need to get the longest period which the school has gone without enrolling or completing learners, using a SQL query. How do I do this?
I'll assume you have access to CTEs and ROW_NUMBER().
First, you need an ordered list of the dates. That is, not two columns, but one. Then you can compare one date to the immediate next date quite simply.
As you have the data in two columns, creating this one ordered list will be relatively expensive. I hope for your sake that you don't have a huge volume of data.
WITH
all_dates
AS
(
SELECT EnrolmentDate AS event_date FROM yourTable GROUP BY EnrolmentDate
UNION
SELECT CompletionDate AS event_date FROM yourTable GROUP BY CompletionDate
)
,
sequenced_dates
AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY event_date) AS id,
event_date
FROM
all_dates
)
SELECT
MAX(DATEDIFF(DAY, first_event.event_date, second_event.event_date)) AS duration
FROM
sequenced_dates AS first_event
INNER JOIN
sequenced_dates AS second_event
ON first_event.id = second_event.id - 1

Split column in 3

Note: Tried a couple of the answers below (its in Teradata, so some of the answers are giving me syntax errors everywhere)
I hit a brick wall here.
I want to compare year by year in different columns
ID, Year, Revenue
1, 2009, 10
1, 2009, 20
1, 2010, 20
2, 2009, 5
2, 2010, 50
2, 2010, 1
How do I separate it by both ID and Year?
At the end I would like it to look like this
ID, Year, Sum
1, 2009, 30
1, 2009, 20
...
2, 2010, 51
(heavily edited for comprehension)
The best I can give you with the amount of detail you have provided is to break your table into subqueries:
select t1.yr - t2.yr from
(select yr
from the_table where yr = 2010) t1,
(select yr
from the_table where yr = 2010) t2
More detail could be given if we knew which type of database you are using, what the real structure of your table is, etc. but perhaps this will get you started.
something like this:
select id, t2009.year, t.2010.year, t2010.year-t.2009.year diff
from
( select id, year
from mytable
where year = 2009
) t2009
,
( select id, year
from mytable
where year = 2010
) t2010
You will most likely have to do a self-join
SELECT [what you are comparing] FROM [table] t1
[INNER/LEFT] JOIN [table] t2 ON t1.[someID] = t2.[someID]
WHERE t1.year = 2009 AND t2.year = 2010
In the someID would not necessarily have to be an ID, or even an indexed column, but it should be the column you are looking to compare across the years.
E.g. a table called 'Products' with columns/fields
ID
ProductName
Price
Year
You could do:
SELECT t1.ProductName, (t2.Price - t1.Price) As Price_change FROM Products t1
INNER JOIN Products t2 ON t1.ProductName = t2.ProductName
WHERE t1.year = 2009 AND t2.year = 2010
This would be faster is ProductName was a primary key or an indexed column. This would also be faster than using nested selects which are much much slower than joins (when joining on an index).
By your data and your desired output, I think you simply want this:
select ID, Year, SUM(Revenue)
from YourTable
GROUP BY ID, Year
Update
Now, if your first data sample is already a SELECT query, you need to:
select ID, Year, SUM(Revenue)
from (SELECT...) YourSelect
GROUP BY ID, Year
This looks like a good candidate for the ROLLUP command. It will give you automatic sums for the grouped-by columns:
GROUP BY ROLLUP (ID,Year)
More info here.