Select most frequent month of a year in SQLITE3? - sql

I have a table like the following-
year month frequency
---------- ---------- ----------
2501 04 33
2501 03 911
2503 12 377
2503 11 3956
2503 10 1409
2503 07 161
2503 06 66
2504 03 46
How to get the most frequent month of each year to produce
year month frequency
---------- ---------- ----------
2501 03 911
2503 11 3956
2504 03 46

Possible solution is to use join :
select t1.*
from t t1 join (select year, max(freq) freq from t group by year) t2
on t1.year = t2.year and t1.freq = t2.freq
SQLFiddle

The following query provides your solution. SQLFiddle here.
select year, month, max(frequency) frequency
from mytable
group by year
UPDATE:
Your required output had columns year, month, frequency where frequency was the maximum value of frequency per year. So max(frequency) frequency assigns the alias frequency to the query output so that it matches your requirement. Without the alias, the columns would be year, month, max(frequency). Here is the wiki on SQL aliases.

Related

T-SQL Force Select results to have a Primary Key

I have a large set of imperfect data, from this data I reverse engineering a table for the coding used.
For this particular task, it is know that all records with a specific division code should all have the same group ID and plan ID (which are not included in the data) from another source I been able to add a close but imperfect (and incomplete) mapping of the group ID and plan ID. Now I want to work backwards and build a division mapping table. I have gotten data down to a format like this:
Division Year Group Plan Cnt
52 2019 30 101 9031
52 2020 30 101 9562
54 2019 60 602 3510
54 2020 60 602 3385
56 2019 76 904 1113
56 2020 76 905 1125
56 2020 76 001 6
The Division and Year columns should from a primary key. As you can see 56, 2020 is not unique, but by looking at the cnt column it is easy to see that the record with a count of 6 is a bad record and should be dropped.
What I need is a method to return each division and year pair once with the group and plan IDs that have the largest count.
Thank You
I found the answer using the Rank() function and WHERE clause:
SELECT *
FROM (
SELECT Division, Year, Group, Plan_Cd
, RANK() OVER (PARTITION BY Division, Year ORDER BY Cnt DESC ) AS 'rk'
FROM DivisionMap ) R
WHERE rk = 1

How can I join the SUMS from 2 different tables into 1

I have 2 tables
Table 1 = LOG
Site Year Quarter SF Seats
------ ------ --------- ------ -------
NYC 2019 Q1 1000 34
NYC 2019 Q1 1289 98
CHI 2019 Q1 976 17
NYC 2019 Q2 3985 986
Table 2 = Headcount
Site Year Quarter HC
------ ------ --------- -------
NYC 2019 Q1 63
NYC 2019 Q1 34
CHI 2019 Q1 73
NYC 2019 Q2 23
I need to be able to join these tables together and display the sum of SF, Seats, and HC for each distinct Site, Quarter, and Year
For example the output should be:
Site Year Quarter HC SF Seats
------ ------ --------- ------- ------ -------
NYC 2019 Q1 97 2289 132
NYC 2019 Q2 23 3985 986
CHI 2019 Q1 73 976 17
Here is my SQL Query:
SELECT DISTINCT SITE,
YEAR,
QUARTER,
SEATS,
SF,
HC
FROM
(SELECT DISTINCT site SITE,
YEAR YEAR,
quarter QUARTER,
sum(SEATS) SEATS,
sum(SF) SF
FROM Headcount
GROUP BY SITE,
YEAR,
QUARTER) A
CROSS JOIN
(SELECT DISTINCT sum(HC) HC
FROM Headcount
GROUP BY site,
YEAR,
quarter, HC) C
But I am getting this error message "Column HC contains an aggregation function, which is not allowed in GROUP BY"
Any idea what I'm doing wrong and why this query isnt working?
The reason for the error is that in the last sub query you have HC in the group by clause, while you also aggregate with sum(HC). That is not allowed. It should be one or the other.
However, a cross join will combine all rows from the first sub query, with all rows from the second. Surely this is not what you need.
Also, distinct is not needed when you use group by. You cannot get duplicates with group by.
I would suggest using union all:
SELECT SITE,
YEAR,
QUARTER,
SUM(HC),
SUM(SEATS),
SUM(SF)
FROM (
SELECT SITE,
YEAR,
QUARTER,
HC,
null AS SEATS,
null AS SF
FROM Headcount
UNION ALL
SELECT SITE,
YEAR,
QUARTER,
null,
SEATS,
SF
FROM Log
) AS base
GROUP BY SITE,
YEAR,
QUARTER
With a N-M relationships between both tables, you would need to do the aggregation in subqueries, and then join the results together :
SELECT h.*, l.SF, l.Seats
FROM
(
SELECT site, year, quarter, SUM(SF) SF, SUM(Seats) Seats
FROM LOG
GROUP BY site, year, quarter
) l
INNER JOIN (
SELECT site, year, quarter, SUM(HC) HC
FROM Headcount
GROUP BY site, year, quarter
) h
ON h.site = l.site AND h.year = l.year AND h.quarter = l.quarter

Oracle SQL : Getting average for past 3 month and add additional column

I have below table in Oracle and i need to create a view from this table to calculate of the average score for the past 3 months in additional column.
Name YearMonth Score
Vince 201507 97
Vince 201508 95
Vince 201509 94
Vince 201510 91
Vince 201511 98
Vince 201512 95
Vince 201501 93
Expected output:
Name YearMonth Score Average
Vince 201507 97
Vince 201508 95
Vince 201509 94 95.33 ((97+95+94)/3)
Vince 201510 91 93.33 ((95+94+91)/3)
Vince 201511 98 94.33 ((94+91+98)/3)
Vince 201512 95 94.67 ((91+98+95)/3)
Vince 201501 93 95.33 ((98+95+93)/3)
How can I do it using SQL? Thank you for the help
You can do this with a window function:
select name,
yearmonth,
score,
avg(score) over (order by to_date(yearmonth, 'yyyymm') range between interval '3' month preceding and current row) as average
from scores;
The above assumes yearmonth is a varchar column, otherwise the to_date() wouldn't work.
This is not exactly what your sample output is, because the first two rows will have an average that is equal to the row's score (because there are no 3 previous months for those two rows). If you really do need those averages to be null, you can do something like this:
select name,
yearmonth,
score,
case
when row_number() over (order by to_date(yearmonth, 'yyyymm')) > 2 then
avg(score) over (order by to_date(yearmonth, 'yyyymm') range between interval '3' month preceding and current row)
else null -- not really necessary, just for clarity
end as average
from scores;
select name, year_month, score,
(score +
lag(score, 1) over (partition by name, year_month order by score) +
lag(score, 2) over (partition by name, year_month order by score)) / 3 average
from my_table

Oracle sql split amounts by weeks

So I have a table like:
UNIQUE_ID MONTH
abc 01
93j 01
acc 01
7as 01
oks 02
ais 02
asi 03
asd 04
etc
I query:
select count(unique_id) as amount, month
from table
group by month
now everything looks great:
AMOUNT MONTH
4 01
2 02
1 03
etc
is there a way to get oracle to split the amounts by weeks?
the way that the result look something like:
AMOUNT WEEK
1 01
1 02
1 03
1 04
etc
Assuming you know the year - lets say we go with 2014 then you need to generate all the weeks a year
select rownum as week_no
from all_objects
where rownum<53) weeks
then state which months contain the weeks (for 2014)
select week_no, to_char(to_date('01-JAN-2014','DD-MON-YYYY')+7*(week_no-1),'MM') month_no
from
(select rownum as week_no
from all_objects
where rownum<53) weeks
Then join in your data
select week_no,month_no, test.unique_id from (
select week_no, to_char(to_date('01-JAN-2014','DD-MON-YYYY')+7*(week_no-1),'MM') month_no
from
(select rownum as week_no
from all_objects
where rownum<53) weeks) wm
join test on wm.month_no = test.tmonth
This gives your data for the each week as you described above. You can redo your query and count by week instead of month.

Getting a variable end of year date and value from MS Access table using SQL

I have some data is that is daily (day on day) closing figures for a tracked supply and is in one MS Access table that has 2 columns - Dates (the date), PXLast(the day's closing figure)).
I have daily data from Jan 1991 to Aug 2013 and I wanted to get the percentage change of PXLast at every year end compared to last year year end as follows:
Year | Percentage Change of PXLast(Year on Year)
1991 | 15.2%
1992 | 9.2%
The year end date varies (not always 31st ) and I am going about getting the last PXLast value by:
1.Get the max date in Dec every year: results in MyYear, MyMonth, MyDay
2.Combine it using DateSerial(MyYear, MyMonth, MyDay)
3.Join the resulting query to the table and inner join on the date column
4.Get the PXLast value
SELECT EndDates.EndDates, NSE20.PX_LAST AS LookPoint
FROM NSE20 INNER JOIN
(SELECT DateSerial([MyYear],[MyMonth],[MyDay])
AS EndDates FROM (SELECT 12 AS MyMonth, MyDay, MyYear FROM
(SELECT Max(Day([Dates])) AS MyDay, Year([Dates]) AS MyYear
FROM NSE20 WHERE (((Month([Dates]))=12))
GROUP BY Year([Dates])) AS EndYearValues)
AS EndValueDates)
AS EndDates ON NSE20.Dates = EndDates.EndDates;
Could anyone assist me get the corresponding value using a query for previous year end
eg for 29 Dec 2006, it should show the current value and show the value for 31 Dec 2005
in the same row ie
Year | Current Year End| Previous Year End
2005 | 3449.00 | 4611.19
2006 | 9.2% |3449.00
Any help is appreciated.
Any suggestions to a better way of doing this is very very welcome....
Let's assume that you have some test data in a table named [NSE20] that looks like this
Dates PXLast
---------- ------
2010-07-01 131
2010-12-31 130
2011-11-12 123
2011-12-30 125
2012-01-03 127
2012-12-31 129
I'd start by creating a saved query in Access named [NSE20_year_ends] that identifies the year-end dates by (calendar) year:
SELECT Year(Dates) AS CalendarYear, Max(Dates) AS YearEndDate
FROM NSE20
GROUP BY Year(Dates)
That will produce
CalendarYear YearEndDate
------------ -----------
2010 2010-12-31
2011 2011-12-30
2012 2012-12-31
Then I'd create another saved query named [NSE20_year_end_balances] to extract the closing balances for each year:
SELECT NSE20_year_ends.CalendarYear, NSE20.PXLast
FROM
NSE20
INNER JOIN
NSE20_year_ends
ON NSE20.Dates = NSE20_year_ends.YearEndDate
That will give us
CalendarYear PXLast
------------ ------
2010 130
2011 125
2012 129
Now we can do a self-join on that query to calculate the percentage change
SELECT
y1.CalendarYear,
(y1.PXLast - y0.PXLast) / y0.PXLast * 100 AS PctChange
FROM
NSE20_year_end_balances y1
INNER JOIN
NSE20_year_end_balances y0
ON y0.CalendarYear = y1.CalendarYear - 1
resulting in
CalendarYear PctChange
------------ -----------------
2011 -3.84615384615385
2012 3.2