Oracle : Selecting multiple columns with avg function - oracle

I am trying to display the average values of each player on a row by row basis with the player name
I have looked throughout the oracle docs and previous question asked by other people on stack overflow. I have only come across on how to select average value group by their record id and how to select avg using subquery
For an example,
What i found is to get the average by each row by
select round(avg(g1+g2+g3+g4)) as "Average Score" from ch_user group by playerid;
Do note that i didnt display my PlayerID shown in the picture .
If i were to select player and avg , it will give me ORA-01427. I have tried
select player, (select round(avg(g1+g2+g3+g4)) from ch_user group by playerid) as "Average Score" from ch_user;
But its prompting the error ORA-01427. single-row subquery returns more than one row.
Thank you in advance
UPDATED
I have already found the solution to the problem and i am able to implement it to my query based on #Boneist answer.
However, i find the query long, is there by any chance i could simplify the query ?
My query is
select first_name || ' ' || last_name as Player,game_1 as G1 , game_2 as g2 ,
game_3 as g3, game_4 as G4,total_score as "Total Tournament Score",
round(avg(game_1+game_2+game_3+game_4)) as "Average Score" from ch_user
group by playerid, first_name,last_name,game_1,game_2,game_3,game_4,total_score;

I think you've overthought this... all you need to do is add player into the select list in your first query and add player into the group by:
select player,
round(avg(g1 + g2 + g3 + g4)) as "Average Score"
from ch_user
group by playerid, player;

I think you want to group the data by player_id, but display player name and average. Check if this helps.
select player_name,round(avg(g1+g2+g3+g4)) "Average"
from ch_user
group by player_id,player_name;

Related

How to calculate longest period between two specific dates in SQL?

I have problem with the task which looks like that I have a table Warehouse containing a list of items that a company has on stock. This
table contains the columns ItemID, ItemTypeID, InTime and OutTime, where InTime (OutTime)
specifies the point in time where a respective item has entered (left) the warehouse. I have to calculate the longest period that the company has gone without an item entering or leaving the warehouse. I am trying to resolve it this way:
select MAX(OutTime-InTime) from Warehouse where OutTime is not null
Is my understanding correct? Because I believe that it is not ;)
You want the greatest gap between any two consecutive actions (item entering or leaving the warehouse). One method is to unpivot the in and out times to rows, then use lag() to get the date of the "previous" action. The final step is aggregation:
select max(x_time - lag_x_time) max_time_diff
from warehouse w
cross apply (
select x_time, lag(x.x_time) over(order by x.x_time) lag_x_time
from (
select w.in_time as x_time from dual
union all select w.out_time from dual
) x
) x
You can directly perform date calculation in oracle.
The result is calculated in days.
If you want to do it in hours, multiply the result by 24.
To calculate the duration in [day], and check all the information in the table:
SELECT round((OutTime - InTime)) as periodDay, Warehouse .*
FROM Warehouse
WHERE OutTime is not null
ORDER BY periodDay DESC
To calculate the duration in [hour]:
SELECT round((OutTime - InTime)*24) AS periodHour, Warehouse .*
FROM Warehouse
WHERE OutTime is not null
ORDER periodHour DESC
round() is used to remove the digits.
Select only the record with maximum period.
SELECT *
FROM Warehouse
WHERE (OutTime - InTime) =
( SELECT MAX(OutTime - InTime) FROM Warehouse)
Select only the record with maximum period, with the period indicated.
SELECT (OutTime - InTime) AS period, Warehouse.*
FROM Warehouse
WHERE (OutTime - InTime) =
( SELECT MAX(OutTime - InTime) FROM Warehouse)
When finding the longest period, the condition where OutTime is null is not needed.
SQL Server has DateDiff, Oracle you can just take one date away from the other.
The code looks ok. Oracle has a live SQL tool where you can test out queries in your browser that should help you.
https://livesql.oracle.com/

Type wise summation and subtracting in oracle

I have two table of my store and working on Oracle. Image First table describe about my transaction in store, there are two types of transaction (MR & SR), MR means adding products in Store and SR means removing products from my storage. What I wanted to do get the final closing of my storage. After transaction final Quantity every products as shown in Image. I have tried many solution but can't finish it. so I could not show now. Please help me to sort this problem. Thanks
You can use case as below to decrease and increase the quantity based on type and then group by Name and find the sum of quantity derived from the case statement to get your desired result.
select row_number() over (order by a.Name) as Sl,a.Name, sum(a.qntity) as qntity
from
(select t2.Name,case when t1.type='MR' then t2.qntity else -(t2.qntity) end as qntity
from table1 t1,table2 t2 where t1.oid=t2.table01_oid) a
group by a.Name;
This query will provide result as below:
SL NAME QNTITY
1 Balls 0
2 Books 6
3 Pencil 13

Impala : Running sum of 1 hour

I want to count records of each ID with in 1 Hour. I tried out some IMPALA queries but without any luck.
I have input data as follows:
And expected output would be:
I tried :
select
concat(month,'/',day,'/',year,' ',hour,':',minute) time, id,
count(1) over(partition by id order by concat(month,'/',day,'/',year,' ',hour,':',minute) range between '1 hour' PRECEDING AND CURRENT ROW) request
from rt_request
where
concat(year,month,day,hour) >= '2019020318'
group by id, concat(month,'/',day,'/',year,' ',hour,':',minute)
But I got exception.
RANGE is only supported with both the lower and upper bounds UNBOUNDED or one UNBOUNDED and the other CURRENT ROW.
Any suggestion/help would be appreciated.
Thank you in advance!
I think you are looking for counts for the same hour across days for a given id. You can simply use row_number to do this.
select time,id,row_number() over(partition by id,hour order by concat(month,'/',day,'/',year,' ',hour,':',minute)) as total
from tbl

How can I display Row Number in Cross-Tab?

I'm looking for a way to display row number in my cross-tab.
I tried searching online for the answer on how to do it but I haven't found anything useful.
So I'm turning to the good people on Stack Overflow.
The reason that I want to do this, if it's even possible, is because many clients in the company I started working at asked to have a row number in the cross-tab.
I am using Visual Studio 2013 and Crystal Reports.
So is there any basic ( easy ) way to do this in Crystal Reports?
For example, I have a cross-tab that displays unit of measure and amounts.
https://imgur.com/a/lOjCq
But I would like my cross-tab to be like:
Amount
1. Total -38
2. KG
3. kut 9
4. LIT. 4
5. m -32
6. proc
7. KoŠ¼ -19
Please keep in mind that I only started working with Crystal Reports this week, so this is all new to me. And the cross-tab in the picture is just a random one I made to explain what I need.
Thank You in advance.
In order to show Row Number in your CrossTab you will need to first put Row Number in the Stored Procedure that sends data to your report.
In order to understand it better i will first show you how my data looks before i add a Row number(Pic 1).
Code:
select
a.S_ID as ID,
osn.sifra as BasicGoodsCode,
osn.naziv as BasicGoods,
null,
a.RobaSifra as GoodsCode,
a.Roba as Goods,
a.Detalj as Detail,
a.DetaljDodatak as DetailsAddon
from NP_Stavke s
left join RobaGrupe osn on osn.id = s.RobaId
left join #A a on a.S_ID = s.Id
order by BasicGoodsCode, ID
Pic 1: As you can see I have 3 different Ids for BasicGoods which means that I have 3 Rows in my CrossTab
Columns ID, BasicGoodsCode and BasicGoods are going to be Rows in my CrossTab.
Values from column DetailsAddon are going to be my columns in CrossTab.
Columns GoodsCode, Goods and Detail are going to be values in my CrossTab.
Column Pieces is not important.
Now that you know how everything looks we can start with adding a Row Number to our CrossTab.
Step 1:
First thing that you need to do is to add a Row number in table in your stored procedure.
To do this I used DENSE_RANK()
depending on your data you might need to use ROW_NUMBER() or maybe even something else. I used DENSE_RANK() because I needed my row number to change once S_ID changes.
Code:
select
a.S_ID as ID,
DENSE_RANK() OVER (ORDER BY osn.sifra, s.Id asc) as BasicGoodsRowNo, // THIS IS ADDED
osn.sifra as BasicGoodsCode,
osn.naziv as BasicGoods,
null as Pieces,
a.RobaSifra as GoodsCode,
a.Roba as Goods,
a.Detalj as Detail,
a.DetaljDodatak as DetailsAddon
from NP_Stavke s
left join RobaGrupe osn on osn.id = s.RobaId
left join #A a on a.S_ID = s.Id
order by BasicGoodsCode, ID
Lets take a look at how our data looks now(Pic 2)
As you can see we added a Row Number that changes when Id changes.
IMPORTANT: Row Number has to be ether Integer or Decimal in the DataTable that you are using in your report if it's not it will not work correctly.
Step 2:
We've done the 'hard' part now it's time to put Row number in our CrossTab.
When you create a CrossTab or when right click CrossTab and then click on 'Cross-Tab Expert...' it will open a window like this one and in it in the Row section you will insert your Row Number Column(in my case and as you can see in the code above the name of my Row Number Column is 'BasicGoodsRowNo').
Step 3:
Since you don't want to show only the Row number in the report left click on your Row and then click on 'Group Options...'(Pic 4)
Once the new window appears click on 'Options' tab then check the 'Customise group name field' then click on 'Use a formula as group name' and then on 'x-2'(Pic 5)
Step 4:
Enter a formula like this one:
toText( {myTbl.BasicGoodsRowNo}, 0, "" ) + '. ' + {myTbl.BasicGoodsCode} + ' ' + {myTbl.BasicGoods}
Of course your formula will not be exactly like mine since you will not have the same columns as I do. The only part of this formula that you HAVE to have is toText( {myTbl.BasicGoodsRowNo}, 0, "" ) where instead of {myTbl.BasicGoodsRowNo} you will put your row number column. You will need toText since if you dont have that and you want to show a String after your Row Number it will give you an error because RowNumber is an integer field.
GJ YOU ARE ALL DONE AND IT WASN'T THAT HARD WAS IT
How My CrossTab looks once RowNumber is added
Now there is a way to simplify this process and that is:
Step 1:
In your stored procedure create 2 columns. One will show Row Number and the other will show Value that will be displayed as CrossTab row.
Code:
select
a.S_ID as ID,
DENSE_RANK() OVER (ORDER BY osn.sifra, s.Id asc) as BasicGoodsRowNo, // RowNumber
CONVERT(varchar(10), DENSE_RANK() OVER (ORDER BY osn.sifra, s.Id asc)) + '. ' + osn.sifra + ' ' +osn.naziv as BasicGoods, // Value that will be displayed in CrossTab Row
null as Pieces,
a.RobaSifra as GoodsCode,
a.Roba as Goods,
a.Detalj as Detail,
a.DetaljDodatak as DetailsAddon
from NP_Stavke s
left join RobaGrupe osn on osn.id = s.RobaId
left join #A a on a.S_ID = s.Id
order by BasicGoods, ID
As you can see Column BasicGoodsRowNo did not change and will still display the same values as before and I have deleted the clumns BasicGoodsCode and BasicGoods and replaced them with this
CONVERT(varchar(10), DENSE_RANK() OVER (ORDER BY osn.sifra, s.Id asc)) + '. ' + osn.sifra + ' ' +osn.naziv as BasicGoods,
The BasicGoods column will show BasicGoodsRowNo + BasicGoodsCode + BasicGoods.
Step 2:
Step 2 is the same as before.
Step 3:
Once you click on your row and on 'Group Options' go to 'Options' tab again then check the 'Customise group name field' check box again and after that instead clicking on 'Use a formula as group name' click on 'Choose from existing field' and from a combo box select the column you want to show as Row Value in your CrossTab. In my Case that is 'BasicGoods' column (Pic 7).
I used the first method since depending on what user decides I may not show CrossTab at all and I may not show BasicGoods but if you only have CrossTab in your report you can use the second, shorter and easier, method.
If you have any questions feel free to ask.

How can i solve this query in sql oracle?

It's an exercise that is not solved in the book in which I am studying.
The goal is to find the seller who has had the highest number of sales per month,
during all the months for which there is registered information. The problem is that I do not know how to divide tuples into periods of one month.
First table is:
Table Sellers
Id_seller
Name_Product
And the other one is:
Table Product
Name_Product
View_datetime
Budget
What did i do?
I made this query:
SELECT id_seller FROM(SELECT id_seller, COUNT(id_seller)
FROM SELLERS INNER JOIN PRODUCT
ON SELLERS.name_product = PRODUCT.name_product
GROUP BY id_seller HAVING COUNT(id_seller)>= 1
ORDER BY 2 DESC)
WHERE ROWNUM = 1;
The query returns me the seller that most sales has done, but not "per month since there are records" as the statement asks. Any ideas? I'm so lost...
The idea is to compare the total sales of each salesman in this month (sysdate), with those of a month ago, two months ago ... so long as there are older records. And get the maximum from each seller. And then you print the seller with more sales from the previous list. If a seller sells 400 products this month(April, the sysdate), but another seller sold in October last year 500, the result would be the second seller . That's what I do not know how to do.
Thanks ^^
You could try this query
select MonthName, id_seller, max(TotalSales) from (
select to_char(sysdate, 'Month') MonthName, sellers.id_seller, count(sellers.id_seller) TotalSales
from sellers inner join product
on sellers.name_product = product.name_product
group by to_char(view_datetime, 'Month'), sellers.id_seller
) tab
group by MonthName, id_seller
There are a few points to make...
The tables are weird. I assume your table sellers would better be called sales, right?
In this example, having count... >= 1 is a no-op. Count could only be 0 if there were no rows at all, in which case there would be no row in the group- by output. You can just leave this count away, here.
To get the sales per month, just add the month to the group by. I.e. group by id_seller, To_date(view_datetime,'YYYYMM').

Resources