Calculate grand total in oracle sql developer - sql

How to calculate grand total in query in SQL developer in oracle.
Break on report
Compute Sum is not working in SQL developer.It works only in SQL plus.
Don't want to use group function also.
Is there any way to run a query in SQL developer and show the total at the end of the results/rows.
Also want to use it in jdbc java the query
For Example , i need to select a table and list all records matching certain criteria and show the sum at the end of the records
Select volume, value , *.t1 from table1 t1 where trunc(create_date) = trunc(sysdate)
This will display say 50 records..i want to display at the end of all records under column volume and value ,the grand total of these 2 columns.
Volume value xxx yy zzzz
25 123.5 aa bb cc
35 10 a c b
50 100 c nn xc
-- --
110 233.5

You can use the below query to achieve the result -
SELECT volume,
value ,
t1.*
FROM table1 t1
WHERE TRUNC(create_date) = TRUNC(SYSDATE)
UNION ALL
SELECT SUM(volume),
SUUM(value),
NULL,
NULL,
... -- Add other NULLS according to your column list in table1.
FROM table1;

"I don't want" is a poor reason.
How come you can & want to use SQL*Plus' commands (which won't work elsewhere), but standard SQL capabilities are out of your sight? I'd suggest you to reconsider what you said & thought.
If you do, rollup might be a nice option for you.
SQL> select deptno,
2 sum(sal) sum_sal,
3 sum(comm) sum_comm
4 from emp
5 group by rollup(deptno);
DEPTNO SUM_SAL SUM_COMM
---------- ---------- ----------
10 8750
20 10875
30 9400 2200
29025 2200
SQL>

You can use ROLLUP FUNCTION here.
SELECT SUM (volume) volume,
SUM (value) value,
xxx
FROM table1 t1
WHERE TRUNC (create_date) = TRUNC (SYSDATE)
GROUP BY ROLLUP (xxx)

Related

Is there a way in Teradata convert rows into columns without changing query for new values

I am looking to convert rows to column for a requirement like sum of sales per year. A table like this can be transposed as follows:
Sales Year
100 2,005
200 2,005
300 2,006
100 2,007
200 2,006
300 2,007
'2005' '2006' '2007'
300 500 400
The query I used is
SELECT * FROM test1 PIVOT (SUM("s") FOR "y" IN ( '2005', '2006', '2007' ) ) AS Temp_pivot
However if a new year appears, say 2008 I need to modify the query.
Can I get the output for additional years without modifying the query. Can we do it without procedure or dynamic SQL?
Best Regards
Vaidy
It looks like you can use a sub-query in the IN clause, so what about something like:
SELECT *
FROM test1 PIVOT (
SUM("s") FOR "y" IN (
SELECT year_of_calendar
FROM sys_calendar.calendar
WHERE year_of_calendar >= 2005
-- '2005', '2006', '2007'
)
) AS Temp_pivot
I haven't tested it out, but give it a try and let me know.
TD Manual - Pivot
Thanks for the inputs.
Ravioli, I tried the subquery option but it says "select failed. 3669 more than one value was returned by a subquery".
Any other thoughts?
Best Regards
Vaidy

Setting a maximum value for a variable. Cognos

I started working in BI and I was given a brain teaser since I came from C# and not SQL/cognus.
I get a number. It can be between 0 and a very large number. When I get it and it's below 1,000 everything is dandy. But if it's bigger than or equal to 1,000 , I should use 1,000 instead.
I am not allowed to use conditions, I need it to be pure math, or if I can't then I should use efficient methods.
I thought it would be easy and just use Min() but that works differently in cognus and SQL apparently.
Use the LEAST() function:
Oracle Setup:
CREATE TABLE data ( value ) AS
SELECT 1 FROM DUAL UNION ALL
SELECT 999 FROM DUAL UNION ALL
SELECT 1000 FROM DUAL UNION ALL
SELECT 1001 FROM DUAL;
Query:
SELECT value, LEAST( value, 1000 ) AS output FROM data
Output:
VALUE OUTPUT
----- ------
1 1
999 999
1000 1000
1001 1000

SQL EXTRACT(YEAR FROM MYDATE) not a GROUP BY expression

I have table MYTABLE with columns mydate and quantity of VARCHAR2 type.
|mydate| |quantity|
10/15/2010 15
01/20/2010 20
05/16/2005 30
04/29/2005 50
03/30/2008 5
I want to get:
|year| |quantity|
2010 35
2005 80
2008 5
I try:
SELECT
to_char(mydate,'yyyy') YEAR,
SUM(to_number(quantity))
FROM MYTABLE
GROUP BY
to_char(mydate,'yyyy');
But I get an error
ORA-00979: not a GROUP BY expression
What did I do wrong?
You must put all columns of the SELECT in the GROUP BY or use functions on them which compress the results to a single value (like MIN, MAX or SUM).
A simple example to understand why this happens: Imagine you have a database like this:
FOO BAR
0 A
0 B
and you run SELECT * FROM table GROUP BY foo. This means the database must return a single row as result with the first column 0 to fulfill the GROUP BY but there are now two values of bar to chose from. Which result would you expect - A or B? Or should the database return more than one row, violating the contract of GROUP BY?
Try this
select extract(year from mydate),sum(to_number(quant)) from mytable
group by extract(year from mydate);
SQLFiddle Example

how to calculate separate averages for multiple columns

I have a table that has "months" as columns and "customer ID" as primary key.
I want to average all the values for each month separately for values not equal to 99999.
My current query for a single month is as follows and is working fine:
SELECT Avg([Table1]![Dec10]) AS Expr1
FROM Table1
WHERE ((([Table1]![Dec10])<>99999);
However, when I am trying to add the 2nd month, it is combining the first month's condition with the 2nd month's condition.
SELECT Avg([Table1]![Dec10) AS Expr1, Avg([Table1]![Dec11]) AS Expr2
FROM Table1
WHERE ((([Table1]![Dec10])<>99999) And ([Table1]![Dec11])<>99999);
I need to have each month separate, i.e. calculate the average of Dec10<>99999, and in the second column, calculate the average of Dec11<>99999.
You need to use a Group By clause in your query, and then you can separate your output by months.
In this case it would be convenient to use use GROUP BY.
If you have distinct month values e.g. "jan10", "feb10", "mar12" etc. you can group on the months, and then check that the values is not 99999.
SELECT avg(value), months
FROM tablename
WHERE value <> 99999
GROUP BY months
That is if you have the months stored as literals within a column, but from your database design this may be stored in an other way?
I need to have each month separate, i.e. calculate the average of Dec10<>99999, and in the second column, calculate the average of Dec11<>99999.
In Access 2010, for [Table1]...
CustomerID Dec10 Dec11
---------- ----- -----
1 1 5
2 2 99999
3 99999 0
4 3 7
...the query...
SELECT
DAvg("Dec10", "Table1", "Dec10<>99999") AS AvgOfDec10,
DAvg("Dec11", "Table1", "Dec11<>99999") AS AvgOfDec11
FROM (SELECT COUNT(*) AS n FROM Table1)
...produces:
AvgOfDec10 AvgOfDec11
---------- ----------
2 4

SQL complex view for virtually showing data

I have a table with the following table.
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
9 2000 24
----------------------------------
So this shows stock against some of the hours in which there is a change in the quantity.
Now my requirement is to create a view on this table which will virtually show the data (if stock is not htere for a particular hour). So the data that should be shown is
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
7 2000 20 -- same as hour 6 stock
8 2000 20 -- same as hour 6 stock
9 2000 24
----------------------------------
That means even if the data is not there for some particular hour then we should show the last hour's stock which is having stock. And i have another table with all the available hours from 1-23 in a column.
I have tried partition over by method as given below. But i think i am missing some thing around this to get my requirement done.
SELECT
HOUR_NUMBER,
CASE WHEN TOTAL_STOCK IS NULL
THEN SUM(TOTAL_STOCK)
OVER (
PARTITION BY LOCATION
ORDER BY CURRENT_HOUR ROWS 1 PRECEDING
)
ELSE
TOTAL_STOCK
END AS FULL_STOCK
FROM
(
SELECT HOUR_NUMBER AS HOUR_NUMBER
FROM HOURS_TABLE -- REFEERENCE TABLE WITH HOURS FROM 1-23
GROUP BY 1
) HOURS_REF
LEFT OUTER JOIN
(
SEL CURRENT_HOUR AS CURRENT_HOUR
, STOCK AS TOTAL_STOCK
,LOCATION AS LOCATION
FROM STOCK_TABLE
WHERE STOCK<>0
) STOCKS
ON HOURS_REF.HOUR_NUMBER = STOCKS.CURRENT_HOUR
This query is giving all the hours with stock as null for the hours without data.
We are looking at ANSI sql solution so that it can be used on databases like Teradata.
I am thinking that i am using partition over by wrongly or is there any other way. We tried with CASE WHEN but that needs some kind of looping to check back for an hour with some stock.
I've run into similar problems before. It's often simpler to make sure that the data you need somehow gets into the database in the first place. You might be able to automate it with a stored procedure that runs periodically.
Having said that, did you consider trying COALESCE() with a scalar subquery? (Or whatever similar function your dbms supports.) I'd try it myself and post the SQL, but I'm leaving for work in two minutes.
Haven't tried, but along the lines of what Mike said:
SELECT a.hour
, COALESCE( a.stock
, ( select b.stock
from tbl.b
where b.hour=a.hour-1 )
) "stock"
FROM tbl a
Note: this will impact performance greatly.
Thanks for your responses. I have tried out RECURSIVE VIEW for the above requirement and is giving correct results (I am fearing about the CPU usage for big tables as it is recursive). So here is stock table
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
9 2000 24
----------------------------------
Then we will have a view on this table which will give all 12 hours data using Left outer join.
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
7 2000 NULL
8 2000 NULL
9 2000 24
----------------------------------
Then we will have a recursive view which joins the table recursively with the same view to get the Stock of each hour moved one hour up and appended with level of data coming incremented.
REPLACE RECURSIVE VIEW HOURLY_STOCK_VIEW
(HOUR_NUMBER,LOCATION, STOCK, LVL)
AS
(
SELECT
HOUR_NUMBER,
LOCATION,
STOCK,
1 AS LVL
FROM STOCK_VIEW_WITH_LEFT_OUTER_JOIN
UNION ALL
SELECT
STK.HOUR_NUMBER,
THE_VIEW.LOCATION,
THE_VIEW.STOCK,
LVL+1 AS LVL
FROM STOCK_VIEW_WITH_LEFT_OUTER_JOIN STK
JOIN
HOURLY_STOCK_VIEW THE_VIEW
ON THE_VIEW.HOUR_NUMBER = STK.HOUR_NUMBER -1
WHERE LVL <=12
)
;
You can observe that first we select from the Left outer joined view then we union it with the left outer join view joined on the same view which we are creating and giving it its level at which data is coming.
Then we select the data from this view with the minimum level.
SEL * FROM HOURLY_STOCK_VIEW
WHERE
(
HOUR_NUMBER,
LVL
)
IN
(
SEL
HOUR_NUMBER,
MIN(LVL)
FROM HOURLY_STOCK_VIEW
WHERE STOCK IS NOT NULL
GROUP BY 1
)
;
This is working fine and giving the result as
----------------------------------
Hour Location Stock
----------------------------------
6 2000 20
7 2000 20 -- same as hour 6 stock
8 2000 20 -- same as hour 6 stock
9 2000 24
10 2000 24
11 2000 24
12 2000 24
----------------------------------
I know this is going to take huge CPU for large tables to get the recursion work ( we are limiting the recursion to only 12 levels as 12 hours data is needed to stop it go into infinite loop). But I thought some body can use this for some kind of Hierarchy building. I will look for some more responses from you guys on any other approaches available. Thanks. You can have a look at Recursive views in the below link for teradata.
http://forums.teradata.com/forum/database/recursion-in-a-stored-procedure
The most common uses of view is, the removal of complexity.
For example:
CREATE VIEW FEESTUDENT
AS
SELECT S.NAME,F.AMOUNT FROM STUDENT AS S
INNER JOIN FEEPAID AS F ON S.TKNO=F.TKNO
Now do a SELECT:
SELECT * FROM FEESTUDENT