Query for generating month level & YTD level data - sql-server

Write SQL Queries to -
Given - Day level Sales Data for different Companies
1) Create Month Level , YTD Level Data for the given data.
YTD- Year to Date
YTD(Mar) = Jan + Feb +Mar
2) Create Overall level on the basis of Company for the data created in Step 1. Mark it as "Industry"
Eg: Industry = CompA + CompB + CompC + CompD
3) Calculate Month and YTD Level Share( both Value , Volume) for the data created after Step 2.
Calculation of Share - Comp / Industry.
I get that we can use partition by in over clause but in general i don't understand the question.
schema:
[Period] - date
[Company]- nvarchar
[Metric] - nvarchar
[Values] - Float
Period Company Metric Values
01-01-2018 CompA Sales Vol 72947.30664
02-01-2018 CompA Sales Vol 21553.65941
03-01-2018 CompA Sales Vol 777.6831962
04-01-2018 CompA Sales Vol 34871.11234
05-01-2018 CompA Sales Vol 42598.06526
I tried using partition by month & year. but I'm not clear if this is what is expected.
SELECT YEAR([Period]) AS Year,
MONTH([Period]) as month,
MTD = SUM([Values]) OVER (PARTITION BY year([period]),month([period]) order by period),
YTD = SUM([Values]) OVER (PARTITION BY Year([period]) order by period)
FROM DP

From the sounds of the question it seems like what is being asked is the expression of layers of totals.
Your query works well and does everything required except for the total for the industry.
The query below uses "rollup" which allows you to generate hierarchical groupings based on the columns running left to right. As such you will get a grand total for all industries, a total for all years per company, and a total for all months per year per company.
declare #sales table
(
[Period] date,
[Company] nvarchar(50),
[Metric] nvarchar(50),
[Values] float
);
insert #sales ([Period], [Company], [Metric], [Values])
values
('01-01-2018', 'CompA', 'Sales Vol', 72947.30664),
('02-01-2018', 'CompA', 'Sales Vol', 21553.65941),
('03-01-2018', 'CompA', 'Sales Vol', 777.6831962),
('04-01-2018', 'CompA', 'Sales Vol', 34871.11234),
('05-01-2018', 'CompA', 'Sales Vol', 42598.06526);
SELECT coalesce(Company,'Industry') as Company, coalesce(cast(YEAR([Period]) as nvarchar(50)), 'All Years') AS Year,
coalesce(cast(MONTH([Period])as nvarchar(50)),'All Months') as month, coalesce(sum([values]),0) as sales
FROM #sales
group by rollup (company, year([period]), month([period]))

Related

postgresql count number of employees per year

Columns: id, first_name, last_name, start_date, end_date
NULL allowed only in end-date.
This works for showing how many people started in a particular year:
SELECT
to_char(date_trunc('year', start_date)::date, 'YYYY') AS "Year",
COUNT(*) AS "New Employees"
FROM employees
GROUP BY date_trunc('year', start_date)
ORDER BY date_trunc('year', start_date) ASC
I cannot find a solution to display a list of years with the total number of employees in a particular year.
The assumption is that e.g. in 2022 I would count those with end_date = null AND end_date = 2022.
You need a list of all relevant years, that is to say, all years from the earliest starting date until the current year. Then count the number of active employees for each year.
PostgreSQL provides the useful generate_series function for creating the range of years. You can use coalesce to replace an empty end_date with the current date, available from current_date. The resulting query is
with years(year) as (
select generate_series(
date_trunc('year', (select min(start_date) from employees)),
date_trunc('year', current_date),
interval '1 year'
)
)
select to_char(year, 'yyyy') as year, count(*)
from years
join employees on start_date < year + '1 year'
and coalesce(end_date, current_date) >= year
group by 1
order by 1;

How to generate AutoIncrement number with prefix of financial year?

My Client wants to generate a code for every ticket number that goes into database based on the financial year they are working (April current year to March next year) and number needs to reset to 0 where the financial year changes
Example:
ID
17/18/0000001
17/18/0000002
...
18/19/0000001
18/19/0000002
...
If the financial year is stored in database like starting an ending month and year. How we can check that this is the next year broda! reset the numbers.
I wouldn't attempt to try and maintain such a counter internally. Rather, I would generate at the time of querying. The query below assumes that your table does have a single ordinary auto increment counter ID as well as a year int column for the fiscal year. We can use the following to generate the counter you want:
SELECT
RIGHT(CONVERT(varchar(4), year), 2) + '/' +
RIGHT(CONVERT(varchar(4), year + 1), 2) + '/' +
RIGHT('0000000' +
CAST(ROW_NUMBER() OVER (PARTITION BY year ORDER BY ID) AS VARCHAR), 7)
FROM yourTable;
Demo
Client is always right. Suppose you have a table
create table #trans(
id int identity(1,1),
transDate datetime
--other fields
)
--the table is filled
declare #dStart date='20160401', --start and end dates
#dEnd date='20170331' --of the first financial year
;with fy as ( -- fill following years
select 1 id, #dStart dStart, #dEnd dEnd
union all
select id+1,DATEADD(year,1,dStart),DATEADD(year,1,dEnd)
from fy
where id<5 --"majic" 5 is arbitrary
)
select dStart,dEnd,t.*,
right(cast(year(dstart) as varchar),2)+'/'+right(cast(year(dEnd) as varchar),2)+'/' -- F.Y. label
+ FORMAT( ROW_NUMBER() over(
partition by right(cast(year(dstart) as varchar),2)+'/'+right(cast(year(dEnd) as varchar),2)+'/' --restart numbering each F.Y.
order by t.id),'000000') ticket
from fy
inner join #trans t on cast(t.transDate as date) between fy.dStart and fy.dEnd
And have what the Client wants.
Disclaimer: If some data are deleted then ticket numbering change.

SQL- Finding a gap that is x amount of months with the same foreign key

I am editing this to clarify my question.
Let's say I have a table that holds patient information. I need to find new patients for this year, and the date of their prescription first prescription when they were considered new. Anytime there is a six month gap they are considered a new patient.
How do I accomplish this using SQL. I can do this in Java and any other imperative language easily enough, but I am having problems doing this in SQL. I need this script to be run in Crystal by non-SQL users
Table:
Patient ID Prescription Date
-----------------------------------------
1 12/31/16
1 03/13/17
2 10/10/16
2 05/11/17
2 06/11/17
3 01/01/17
3 04/20/17
4 01/31/16
4 01/01/17
4 07/02/17
So Patients 2 and 4 are considered new patients. Patient 4 is considered a new patient twice, so I need dates for each time patient 4 was considered new 1/1/17 and 7/2/17. Patients 1 and 3 are not considered new this year.
So far I have the code below which tells me if they are new this year, but not if they had another six month gap this year.
SELECT DISTINCT
this_year.patient_id
,this_year.date
FROM (SELECT
patient_id
,MIN(prescription_date) as date
FROM table
WHERE prescription_date BETWEEN '2017-01-01 00:00:00.000' AND '2017-
12-31 00:00:00.000'
GROUP BY [patient_id]) AS this_year
LEFT JOIN (SELECT
patient_id
,MAX(prescription_date) as date
FROM table
WHERE prescription_date BETWEEN '2016-01-01 00:00:00.000' AND '2016-
12-31 00:00:00.000'
GROUP BY [patient_id]) AS last_year
WHERE DATEDIFF(month, last_year.date, this_year.date) > 6
OR last_year.date IS NULL
Patient 2 in your example does not meet the criteria you specified ... that being said ...
You can try something like this ... untested but should be similar (assuming you can put this in a stored procedure):
WITH ordered AS
(
SELECT *, ROW_NUMBER() OVER (ORDER BY [Prescription Date]) rn
FROM table1
)
SELECT o1.[PatientID], DATEDIFF(s, o1.[Prescription Date], o2.[Prescription Date]) diff
FROM ordered o1 JOIN ordered o2
ON o1.rn + 1 = o2.rn
WHERE DATEDIFF(m, o1.[Prescription Date], o2.[Prescription Date]) > 6
Replace table1 with the name of your table.
I assume that you mean the patient has not been prescribed in the last 6 months.
SELECT DISTINCT user_id
FROM table_name
WHERE prescribed_date >= DATEADD(month, -6, GETDATE())
This gives you the list of users that have been prescribed in the last 6 months. You want the list of users that are not in this list.
SELECT DISTINCT user_id
FROM table_name
WHERE user_id NOT IN (SELECT DISTINCT user_id
FROM table_name
WHERE prescribed_date >= DATEADD(month, -6, GETDATE()))
You'll need to amend the field and table names.

How to Create budget table Using current Actual Table

I have Fact table with 6 metric columns and three date key columns remain all are foreign keys,I need design a Budget table based on that fact table like
1)Current year Budget =last year fact +10%(last year fact)
2)Current Quarter Budget =last Quarter fact +10%(last Quarter fact)
3)Current Month Budget =last Month fact +10%(last Month fact)
Does this pseudocode make any sense?
SELECT
DATEPART(YEAR, GETDATE()),
YearFact * 1.1 AS YearBudget,
QuarterFact * 1.1 AS QuarterBudget,
MonthFact * 1.1 AS MonthBudget
FROM
FactTable
WHERE
DATEPART(YEAR, FactDate) = DATEPART(YEAR, GETDATE()) - 1;

doubled and tripled sql server results

I want to create a specific table but some numeric values are doubled or tripled in the result.
here is the situation:
2 tables: Payments and Expenses
[Payments]: ID, studentID, Amount, DOP (a row in this table is a payment which a student pays it on DOP (date).
[Expenses]: ID, AmountPaid, TimeStamp (a row in this table is an expense bought such as papers or pens... on a specific date(timestamp)
my query is:
select
sum(purchases.amount) as 'Income From Students',
sum(Expenses.amountpaid) as 'Expenses',
sum(purchases.amount-expenses.amountpaid) as 'Net Profit',
datename(month,timestamp) as 'Month',
datepart(year,timestamp) as 'Year'
from expenses,purchases
group by datename(month,timestamp),datepart(year,timestamp)
as the query tells: my table should display for each month and each year the sum of payments, expenses and net profit=payments - expenses.
the problem is, when getting the result, sum(expenses.amountpaid) is always doubled.
so any ideas...
Sounds like you need to specify the relationship between the two tables.
Something like this, I assume:
select
sum(purchases.amount) as 'Income From Students',
sum(Expenses.amountpaid) as 'Expenses',
sum(purchases.amount-expenses.amountpaid) as 'Net Profit',
datename(month,timestamp) as 'Month',
datepart(year,timestamp) as 'Year'
from expenses,purchases
WHERE PURCHASES.DOP = EXPENSES.TIMESTAMP /*Add this*/
group by datename(month,timestamp),datepart(year,timestamp)
SELECT T.INCOME,T.EXPENSE,SUM(T.INCOME)-SUM(T.EXPENSE) AS PROFIT
FROM (SELECT SUM(P.amount) AS Income, SUM(E.amountpaid) AS Expense
FROM Payments P,Expenses E WHERE P.ID=E.ID
GROUP BY datename(month, timestamp), datepart(year, timestamp)) AS T;
I Solved it Guys, After 4 hours of Trying, the query is:
select sum(P.Income) as 'Income from Payments',
sum(E.expense) as 'Expenses',
sum(P.Income)-sum(E.expense) as 'Net Profit',
DateName( month , DateAdd( month , IncomeMonth , 0 ) - 1 ) as 'Month'
from
(select sum(payments.amountpaid) as Income,
month(DOP) as IncomeMonth
from payments group by month(dop)) as P,
(select sum(expenses.amountpaid) as Expense,
month(timestamp) as ExpenseMonth
from expenses
group by month(timestamp))
as E
where
E.Expensemonth=P.IncomeMonth
group by P.IncomeMonth

Resources