How Do I retrieve most Recent record in different years With Date date in different table - sql

I'm working with a database that isn't structured that well and need to retrieve the row with the latest month used in specific years. The main data is stored is stored in the member table and lists one row per member month. The Date for the member month is not specifically stored here but connected by a foreign Date_Key and linked to a Date table. This is where the column for the Year and Month can be derived based on the Date_Key specified in each table. Each row in the Date table represents 1 new month for a year and each of these rows has a unique sequential date_key.
I am using Microsoft SQL Server Studio as the environment
Member Table
MemberKey
Membe_ID
Date_Key
100
1234
89
101
1234
96
102
1234
97
103
1236
96
104
1236
97
Date Table
Date_Key
Year
Month
89
2020
10
90
2020
11
91
2020
12
92
2021
1
93
2021
2
94
2021
3
95
2021
4
96
2021
5
97
2021
6
Looking for the following Results
Member_ID
Year
Month
1234
2020
10
1234
2021
6
1236
2021
6

2020/11 is NOT a date. It is a year/month pair. But it seems like a simple aggregate - select year, max(month) group by year. You join and include member ID so you include that column in the GROUP BY clause to get one row per member per year.
select mbr.Member_ID, dts.Year, max(dts.Month) as Month
from dbo.Members as mbr
inner join dbo.Dates as dts on mbr.Date_Key = dts.Date_Key
group by mbr.Member_ID, dts.Year
order by mbr.Member_ID, dts.Year
;

Related

sql query to find student having average of 90 from last 2 years?

I was trying this on test table
create table years (
yr bigint,
average decimal(10,2),
rollno bigint
)
i created this table year for storing 2 years like 2020 and 2021
average of marks scored in average
Condition is to find only those students whose avg is above 54 from last 2 years.
data is as follows
year average rollno
2021 55.20 1
2020 55.50 1
2020 54.50 2
2020 55.50 3
2021 55.40 3
select rollno
from years
where average > 54
and yr = (YEAR(GETDATE())-1)
and yr = (YEAR(GETDATE())-2)
i tried this query but it is not working when i want to specifically find those values where the condition is true.
if i use this query like this
select rollno
from years
where average > 54
and yr = (YEAR(GETDATE())-1) or yr = (YEAR(GETDATE())-2)
it works but doesnt give me the desired result.
result i want is as follows
year average rollno
2020 55.50 1
2021 55.20 1
2020 55.50 3
2021 55.40 3
but i am getting roll no 2 in the output
I'm checking your request after a review in you query, seems there are some parentheses missing in your expression.
Follows the example, based on your query
SELECT * FROM years WHERE
average > 55
and --below the bracket P1
(--Open P1
(--Open P2
yr = year(getdate())-1
)--Close P2
or
(--Open P3
yr = year(getdate())-2
)--Close P3
)--Close P1
What does it mean in the WHERE clause is the average > 55(mandatory) AND all what we have inside in the bracket P1 as another condition.
The result
year average rollno
2020 55.50 1
2021 55.20 1
2020 55.50 3
2021 55.40 3
Best Regards

Count by unique values in other fields in Oracle SQL

I have table like this:
Year Month Type
2013 4 31
2013 3 31
2014 5 40
2014 6 41
2015 5 31
2015 7 40
2013 4 31
2013 3 31
2014 5 40
2014 6 41
2015 5 31
2015 7 40
2013 4 31
2013 3 31
I would like to count number of appearance of each combination. So output should be something like this:
Year Month Type Count_of_appearance
2013 3 31 3
2013 4 31 3
etc..
I've been using something like:
SELECT Year,
Month,
Type,
(SELECT COUNT (*)
FROM myTable
WHERE (...im lost in defining a condition in order to make this work...)
AS Count_of_appearance
FROM employee;
I'm lost at defining functional WHERE clause.
Problem is I a have a lot of fields like this and a lot of unique values. Table is 8Gb big.
You are looking for GROUP BY:
SELECT Year, Month, Type, COUNT(*) AS Count_of_appearance
FROM employee
GROUP BY Year, Month, Type
ORDER BY Year, Month, Type;
To ensure that the results are in the right order, you should include an ORDER BY as well.

SSRS: Horizontal alignment on a group

On my dataset I select information from four different years sorted by date and how many subscriptions I had on said date, which looks something like this:
Date Year Subs Day
15/09/2014 2015 57 1
16/09/2014 2015 18 2
17/09/2014 2015 16 3
14/09/2015 2016 10 1
15/09/2015 2016 45 2
16/09/2015 2016 28 3
12/09/2016 2017 32 1
13/09/2016 2017 11 2
14/09/2016 2017 68 3
24/08/2017 2018 23 1
25/08/2017 2018 53 2
26/08/2017 2018 13 3
What I'm trying to do is create an 'Year' Column Group to align them horizontally, but when I do that, this is the result:
result
Expected result:
expected result
Is this achievable in SSRS? I've tried removing the group =(Details), which gives me the desired result, except it only returns one line of information.
Any insight aprreciated.
By default, the Details group causes you to get one row per row in the dataset. In your case, I would suggest grouping the Rows by the Day column and create a column group by Year.
First, create the two groups and add columns inside the column group.
Then, add a row outside and above the Day row group. Place the headings here and then delete the top row. It should look like this:
Now these 4 columns will repeat to the right for each year and you will get rows based on the number of days in your dataset.

How to perform multiple table calculation with joins and group by

I have two tables client and grouping. They look like this:
Client
C_id
C_grouping_id
Month
Profit
Grouping
Grouping_id
Month
Profit
The client table contains monthly profit for every client and every client belongs to a specific grouping scheme specified by C_grouping_id.
The grouping table contains all the groups and their monthly profits.
I'm struggling with a query that essentially calculates the monthly residual for every subscriber:
Residual= (Subscriber Monthly Profit - Grouping monthly Profit)*(average subscriber monthly profits for all months / average profits for all months for the grouping subscriber belongs to)
I have come up with the following query so far but the results seem to be incorrect:
SELECT client.C_id, client.C_grouping_Id, client.Month,
((client.Profit - grouping.profit) * (avg(client.Profit)/avg(grouping.profit))) as "residual"
FROM client
INNER JOIN grouping
ON "C_grouping_id"="Grouping_id"
group by client.C_id, client.C_grouping_Id,client.Month, grouping.profit
I would appreciate it if someone can shed some light on what I'm doing wrong and how to correct it.
EDIT: Adding sample data and desired results
Client
C_id C_grouping_id Month Profit
001 aaa jul 10$
001 aaa aug 12$
001 aaa sep 8$
016 abc jan 25$
016 abc feb 21$
Grouping
Grouping_id Month Profit
aaa Jul 30$
aaa aug 50$
aaa Sep 15$
abc Jan 21$
abc Feb 27$
Query Result:
C_ID C_grouping_id Month Residual
001 aaa Jul (10-30)*(10/31.3)=-6.38
... and so on for every month for avery client.
This can be done in a pretty straight forward way.
The main difficulty is obviously that you try to deal with different levels of aggregation at once (average of the group and the client as well as the current record).
This is rather difficult/clumsy with simple SELECT FROM GROUP BY-SQL.
But with analytical functions aka Window functions this is very easy.
Start with combining the tables and calculating the base numbers:
select c.c_id as client_id,
c.c_grouping_id as grouping_id,
c.month,
c.profit as client_profit,
g.profit as group_profit,
avg (c.profit) over (partition by c.c_id) as avg_client_profit,
avg (g.profit) over (partition by g.grouping_id) as avg_group_profit
from client c inner join grouping g
on c."C_GROUPING_ID"=g."GROUPING_ID"
and c. "MONTH" = g. "MONTH";
With this you already get the average profits by client and by grouping_id.
Be aware that I changed the data type of the currency column to DECIMAL (10,3) as a VARCHAR with a $ sign in it is just hard to convert.
I also fixed the data for MONTHS as the test data contained different upper/lower case spellings which prevented the join to work.
Finally I turned all column names into upper case to, in order to make typing easier.
Anyhow, running this provides you with the following result set:
CLIENT_ID GROUPING_ID MONTH CLIENT_PROFIT GROUP_PROFIT AVG_CLIENT_PROFIT AVG_GROUP_PROFIT
16 abc JAN 25 21 23 24
16 abc FEB 21 27 23 24
1 aaa JUL 10 30 10 31.666
1 aaa AUG 12 50 10 31.666
1 aaa SEP 8 15 10 31.666
From here it's only one step further to the residual calculation.
You can either put this current SQL into a view to make it reusable for other queries or use it as a inline view.
I chose to use it as a common table expression (CTE) aka WITH clause because it's nice and easy to read:
with p as
(select c.c_id as client_id,
c.c_grouping_id as grouping_id,
c.month,
c.profit as client_profit,
g.profit as group_profit,
avg (c.profit) over (partition by c.c_id) as avg_client_profit,
avg (g.profit) over (partition by g.grouping_id) as avg_group_profit
from client c inner join grouping g
on c."C_GROUPING_ID"=g."GROUPING_ID"
and c. "MONTH" = g. "MONTH")
select client_id, grouping_id, month,
client_profit, group_profit,
avg_client_profit, avg_group_profit,
round( (client_profit - group_profit)
* (avg_client_profit/avg_group_profit), 2) as residual
from p
order by grouping_id, month, client_id;
Notice how easy to read the whole statement is and how straight forward the residual calculation is done.
The result is then this:
CLIENT_ID GROUPING_ID MONTH CLIENT_PROFIT GROUP_PROFIT AVG_CLIENT_PROFIT AVG_GROUP_PROFIT RESIDUAL
1 aaa AUG 12 50 10 31.666 -12
1 aaa JUL 10 30 10 31.666 -6.32
1 aaa SEP 8 15 10 31.666 -2.21
16 abc FEB 21 27 23 24 -5.75
16 abc JAN 25 21 23 24 3.83
Cheers,
Lars

ORACLE order by MONTH

How can I order by month in full name of the month?
And I want to get the results like this below:
FEBRUARY 0 80
MARCH 0 58
APRIL 0 39
This is my 1st simple script:
select to_char(month,'MONTH')month,mo_incoming,mt_outgoing
from t_raw_settlement_tara_yearly
order by month
output:
APRIL 0 39
FEBRUARY 0 80
MARCH 0 58
2nd Script is almost right but I want the month to be in full MONTH
select to_date(to_char(month,'MONTH'),'MONTH')month,mo_incoming,mt_outgoing
from t_raw_settlement_tara_yearly
order by month
output:
2/1/2015 0 80
3/1/2015 0 58
4/1/2015 0 39
You alias to_char(month,'MONTH') to month. Now when you use month in ORDER BY it references the month string. Either use a different alias or qualify the column:
select to_char(month,'MONTH')month,mo_incoming,mt_outgoing
from t_raw_settlement_tara_yearly t
order by t.month