order by Month by fiscal year - sql

I have an excel spreadsheet which contains data like this
Month Value1 FY11Count FY12COunt
----------------------------------------------
jul xxx 23 39
aug yy 33 49
..etc
I am using ODBC to query this data for a dashboard application. I would like to order this data by fiscal year (july,aug....etc till Jun) .
can i add another pseudo column say MonthNo and use some sort of logic to say when Month=Jul then 1, aug then 2..etc and order by that pseudocolumn?
Are there any other suggestions better than this?

not sure if this is not what you mean by "pseudocolumn", but SQL way is this:
order by case Month
when 'jul' then 1
when 'aug' then 2
...
end

ORDER BY CASE
WHEN Month(application_receiving_date) = 1 THEN 13
WHEN Month(application_receiving_date) = 2 THEN 14
WHEN Month(application_receiving_date) = 3 THEN 15
ELSE Month(application_receiving_date) END

Related

Return the first and last value from one column when value from another column changes

I am trying to write a PostgreSQL query to return the first and last dates corresponding to indices. I have a table:
Datetime
Index
March 1 2021
0
March 2 2021
0
March 3 2021
0
March 4 2021
1
March 5 2021
1
March 6 2021
2
In this case, I would want to return:
I am wondering how I would write the PostgreSQL query for this.
I think this can be done with the following:
SELECT MIN("Datetime") AS Start
, MAX("Datetime") AS End
, "Index"
FROM <your_table>
GROUP BY "Index"
ORDER BY "Index"
;

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.

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

How to fetch data according to date in sql

I have a table truck_data with columns truck_no, diesel_filled, source, destination, amount etc
I want to fetch only truck_no and diesel_filled in such way that it will show the details of diesel_filled in each truck through out the month..
Please tell me the SQL query for that - I had tried this query but it's not working
SELECT
truck_no, diesel_filled, date
FROM
truck-data
ORDER BY
date
Please help me out
Thanks in advance
I want output like this
truck_no 1 2 3 4 5 6 7 8 9 etc(date from 1 to 31))
---------------------------------------------------------------------------
xyz 25 22 33 33 22 22 22 0 0 (diesel filled in truck order by date)
pqr 25 25 22 11 22 00 22 55 22
abc 21 15 12 14 13 00 22 00 00
It's still quite unclear what you want. But I think you are mixing presentation and data
SELECT truck_no,diesel_filled,date
FROM truck-data
ORDER BY date
Will give you all rows ordered by date. Presumably you whant some filter on that to only show a specific month.
SELECT truck_no,diesel_filled,date
FROM truck-data
WHERE date >= 2014-10-05 AND date < 2014-11-01 ORDER BY date
To get all the rows for october this year. If date here is a DateTime column.
Then you could change it to:
SELECT truck_no,sum(diesel_filled),Day(date)
FROM truck-data
WHERE date >= 2014-10-05 AND date < 2014-11-01
GROUP BY truck_no
ORDER BY date"
That would give you only one row per day and truck. If disel_filled is a numeric value of some kind.
Then in your UI you would have to do the presentation in any way you prefer. For example in some kind of pivot table like your description above.
You could of course do that in SQL as well, but usually that is a job for the presentation layer.
If you really want to do in SQL you could look into: http://technet.microsoft.com/en-us/library/ms177410(v=sql.105).aspx
If you'r using MsSql.

Counting columns in the same table

I've been trying to develop a cashflow statement in access 2007. This would be so easily done in excel using formulas such as
= SUM (B6:M6) / CountIF(B6:M6)>0
but I cant seem to wrap my head around this when it comes to access. And I need this for every company we enter data on. The cashflow statement is supposed to look like this (Since I can't yet post a pic):
----------------------------------------------------------------------------------------------------------------
Particulars | Jan | Feb | Mar | Apr | Jun | Jul | Aug | Sep | Oct | Nov | Dec | Average |
Sales---------------------->
Salary------>
Transportation----->
and about 10 other items in the row, all with entries for Jan till Dec, however, sometimes we take 6 months worth of data and sometimes for all 12 months. (Imagine a basic excel sheet with items on the first column and headers for the next 12-13 columns).
In access, I made tables for each Item with columns as the months, eg. tblRcpt--> |rcpt_ID|Jan|Feb|... and so on till dec for all the items. Then they will be arranged and presented in an entry form which would be designed to look similar to the above table while later I would query and link them together to presentthe complete cashflow statement.
Now comes the question, I need to Average together the columns (as you can see in the right most column), BUT I only want to average together those months that have been filled (Sometimes in accounting people enter '0' where there is no data), so I cant just sum the columns and divide by twelve. It has to be dynamic, all functions seem to center around counting and averaging ROWs, not COLUMNs.
Thanks for just bearing with me and reading this, any help would be much appreciated.
Try this
(Jan + Feb + ... + Dec) /
( case when Jan = 0 then 0 else 1 end
+ case when Feb = 0 then 0 else 1 end
+ case when Dec = 0 then 0 else 1 end )
as Avg
Your table structure should be:
Particulars | Month | Amount
Sales 1 500
Sales 2 1000
Salary 1 80000
...and so on. You can either not enter rows when you don't have a value for that month, or you can handle them in the SQL statement (as I have below):
SELECT Particulars, AVG(Amount) AverageAmount
FROM MyTable
WHERE NULLIF(Amount, 0) IS NOT NULL
GROUP BY Particulars;