Grand Sum of Rows and Columns SQL - sql

I have a table like below.
Year AccountGroupA AccountGroup B RowSum
2004 15 23 38
2005 10 10 20
2006 8 15 23
2007 16 14 30
ColumnSum 49 62 111
I need grand sum of rows and colums ex:- I need result as 111 in sql query.
The Result needs to be returned from a sql function so ideally should be a single query.

Something like this:
select year,
sum(accountGroupA) as accountGroupA,
sum(AccountGroupB)as accountGroupb,
sum(accountGroupA + AccountGroupB) as rowsum
from the_table
group by year with rollup
This assumes that you only have one row per year or if you have more than one that you actually want to group by year. If neither is the case, you can use a union to achieve the same:
select year, accountGroupA, AccountGroupB, rowsum
from (
select year, accountGroupA, AccountGroupB, accountGroupA + AccountGroupB as rowsum, 0 as union_order
from the_table
union all
select null, sum(accountGroupA), sum(AccountGroupB), sum(accountGroupA + AccountGroupB), 1
from the_table
) t
order by union_order, year
SQLFiddle example: http://sqlfiddle.com/#!6/bd4bc/2

For the ColumnSum the SQL is easy:
SELECT sum(AccountGroupA), sum(AccountGroupB) from YOUR_TABLE
The row sums have to be coded like this:
SELECT (AccountGroupA + AccountGroupB) as RowSum from YOUR_TABLE
Forget about getting the desired result in one SQL statment. Although that is certainly possible with a nasty nested SQL I would not recommend it.

Look at using the ROLLUP Operator.
MSDN Reference: http://technet.microsoft.com/en-us/library/ms189305(v=sql.90).aspx
I've created a SQL fiddle here: http://sqlfiddle.com/#!6/df41d/7
More specifically, the code is here:
select
case when (Grouping(Year)) = 1
then 'ColumnSum'
else isnull(Year, 'Unknown') end as Year,
sum(AccountGroupA) as AccountGroupA,
sum(AccountGroupB) as AccountGroupB,
sum(AccountGroupA + AccountGroupB) as RowSum
from TestTable
group by Year with ROLLUP

Related

LAG function alternative. I need the results for the missing year in between

I have this table so far. However, I would like to obtain the results for 2019 which there are no records so it becomes 0. Are there any alternatives to the LAG funciton.
ID
Year
Year_Count
1
2018
10
1
2020
20
Whenever I use the LAG function in SQL it gives me the results for 2018. However, I would like to get 0 for 2019 and then 10 for 2018
LAG(YEAR_COUNT) OVER (PARTITION BY ID ORDER BY YEAR) AS previous_year_count
untested notepad scribble
CASE
WHEN 1 = YEAR - LAG(YEAR) OVER (PARTITION BY ID ORDER BY YEAR)
THEN LAG(YEAR_COUNT) OVER (PARTITION BY ID ORDER BY YEAR)
ELSE 0
END AS previous_year_count
I'll add on to Nick's comment here with an example.
The YEARS CTE here is creating that table of years as he suggested, the RECORDS table is matching the above posted. Then they get joined together with COALESCE to fill in the null values left by the LEFT JOIN (filled ID with 0, not sure what your case would be).
You would need to LEFT JOIN onto the YEAR table and select the YEAR variable from the YEAR table in the final query, otherwise you'd only end up with only 2018/2020 or those years and some null values
WITH
YEARS AS
(
SELECT 2016 AS YEAR UNION ALL
SELECT 2017 UNION ALL
SELECT 2018 UNION ALL
SELECT 2019 UNION ALL
SELECT 2020 UNION ALL
SELECT 2021 UNION ALL
SELECT 2022
)
,
RECORDS AS
(
SELECT 1 ID, 2018 YEAR, 10 YEAR_COUNT UNION ALL
SELECT 1, 2020, 20)
SELECT
COALESCE(ID, 0) AS ID,
Y.YEAR,
COALESCE(YEAR_COUNT, 0) AS YEAR_COUNT
FROM YEARS AS Y
LEFT JOIN RECORDS AS R
ON R.YEAR = Y.YEAR
Here is the dbfiddle so you can visualize - https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=9e777ad925b09eb8ba299d610a78b999
Vertica SQL is not an available test environment, so this may not work directly but should at least get you on the right track.
The LAG function would not work to get 2019 for a few reasons
It's a window function and can only grab from data that is available - the default for LAG in your case appears to be 1 aka LAG(YEAR_COUNT, 1)
Statements in the select typically can't add any rows data back into a table, you would need to add in data with JOINs
If 2019 does exist in a prior table and you're using group by to get year count, it's possible that you have a where clause excluding the data.

How to divide two values from the different row

I have used this formula.
Quote change = (current month data / previous month data) * 100
Then my data stored on SQL SERVER table look like below :
id DATE DATA
1 2015/01/01 10
2 2015/02/01 20
3 2015/03/01 30
4 2015/04/01 40
5 2015/05/01 50
6 2015/06/01 60
7 2015/07/01 70
8 2015/08/01 80
9 2015/09/01 90
How can i implement this formula on SQL Function ?
For Example
current month is 2015/02/1
Quote change = (Current Month Data / Previous Month Data ) * 100
Quote change =( 15/10)*100
Then if current date is 2015/01/01. Because no data before 2015/01/01, I need to show 0 or #
Sql server 2012 have a window function called LAG that is very useful in situations like this.
Lag returns the value of a specific column in the previous row (specified by the order by part of the over clause).
Try this:
;With cte as
(
SELECT Id, Date, Data, LAG(Data) OVER(ORDER BY Date) As LastMonthData
FROM YourTable
)
SELECT Id,
Date,
Data,
CASE WHEN ISNULL(LastMonthData, 0) = 0 THEN 0 ELSE (Data/LastMonthData) * 100 END As Quote
FROM cte
I've used a CTE just so I wouldn't have to repeat the LAG twice.
The CASE expression is to prevent an exception in case the LastMonthData is 0 or null.
You can use inner join like mentioned below -
select a.*,isnull(cast(a.data/b.data as decimal(4,2))*100,0)
from TableA as a
inner join TableA as b
on b.date = dateadd(mm,-1,a.date)
Let me know if this helps

Querying Data Backward in ORACLE SQL

I have a simple question regarding oracle sql. So i have this table
WEEKNUM DATA
1 10
2 4
3 6
4 7
So i want to make a view that shows like this,
WEEKNUM DATA ACCUM_DATE
1 10 10
2 4 14
3 6 20
4 7 27
I spend hours on this simple one but couldnt get any luck
thanks a lot
SELECT weeknum,
data,
sum(data) over (order by weeknum) accum_data
FROM your_table_name
should work. I'm using the sum analytic function here and assuming that you want to start with the smallest weeknum value and keep increasing the running total as the weeknum values increase. I'm also assuming that you never want to reset the accumulated sum. If you're trying to do something like generating an accumulated sum that restarts each year, you'd want to add a partition by to the analytic function.
You could use a Cross JOin in this case
Query:
select
A.WEEKNUM
, A.DATA
, SUM(B.DATA) DA
from table1 A
cross join table1 B
WHERE A.WEEKNUM>=B.WeekNUM
GROUP BY A.WEEKNUM
, A.DATA
order by A.WEEKNUM
Result:
WEEKNUM DATA DA
1 10 10
2 4 14
3 6 20
4 7 27
Thanks guys but i just found out this method works perfectly,
OVER (ORDER BY WEEKNUM ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS CUMULATIVE_WEIGHT
Or use a sub-select to calculate:
select WEEKNUM, DATA, (select sum(DATA) from tablename t2
where t2.weeknum <= t1.weeknum) as ACCUM_DATE
from tablename t1

SQLite: Get Total/Sum of Column

I am using SQLite and am trying to return the total of one column buy_price in the column TOTAL while at the same time returning all of the data. I do not want/need to group the data as I need to have the data in each returned row.
id date pool_name pool_id buy_price TOTAL
1 09/01/12 azp 5 20
2 09/02/12 mmp 6 10
3 09/03/12 pbp 4 5
4 09/04/12 azp 7 20
5 09/05/12 nyp 8 5 60
When I include something like SUM(buy_price) as TOTAL it only returns one row. I need all rows returned along with the total of all buy_price entries.
It sounds like this is what you are looking for:
select id,
dt,
pool_name,
pool_id,
buy_price,
(select sum(buy_price) from yourtable) total
from yourtable
see SQL Fiddle with Demo
Select * from yourtable
union
select 'Total',
' ',
' ',
' ',
sum(buy_price)
from yourtable
you can add a row on the bottom like this instead of adding a new column...

sql query adding column values

I want to add two columns values of my table and sort it in descending order. E.g:
int_id int_test_one int_test_2
1 25 13
2 12 45
3 25 15
Considering the table above, I want a SQL query which give me the result like below:
int_id sum(int_test_one,int_test_two)
2 57
3 40
1 38
Is there any sql query to do this?
There is not built in function for this kind of horizontal aggregation, you can just do...
SELECT INT_ID, INT_TEST_ONE + INT_TEST_TWO AS SUM FROM TABLE
Did you try what you describe? This works:
SELECT int_id , ( int_test_one + int_test_two ) as s FROM mytable ORDER BY s DESC
You can ommit the "as" keyword if you want.
Try this
SELECT
int_id,
(int_test_one + int_test_two) AS [Total]
FROM
mytable
ORDER BY
[Total] DESC