I have a table called loan with loan amount,annual income, year (MMM-YY format) and member id. I am trying to find the highest loan amount in a year along wit annual income and member id details.
I tried to group the highest loan amount by year using the code
select max(cast(loan_amt as int)),issue_d from loan group by issue_d;
then I wanted also to fetch the member id and annual income information so I wrote the following code
but it is giving me error message for using alias for a column which is cast.
Code:
select a.loan_amt,a.member_id,a.annual_inc,a.issue_d
from
(select loan_amt,member_id,annual_inc,issue_d from loan) a
join
(select max(cast(loan_amt as int)) as ml,issue_d from loan group by issue_d) c
where ((a.issue_d=c.issue_d) and (a.loan_amt=a.ml));
What you want to do is rank the records based on the Amount, per Period, then keep only the top 1 record for each Period.
Use one of the analytic functions that are designed exactly for that purpose -- Hive has a pretty good support of the SQL standard on that topic.
Since you don't say what to do about ties (i.e. what if several loans have the same Amount???) I assume you want just one record chosen randomly...
select X, Y, Z, Period, Amount as TopAmount
from
(select X, Y, Z, Period, cast(StrAmt as double) as Amount,
row_number() over (partition by Period order by cast(StrAmt as double) desc) as TmpRank
from WTF
) TMPWTF
where TmpRank =1
If you want all the records with top Amount then replace row_number with rank or dense_rank (the "dense" stuff would make a difference for the top 2, but not for the top 1)
Related
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/
Please let me know if the following is off topic, or not clear, or too specific, or too complex to understand. I think the following is a challenge to describe, understand and solve.
CIF=cost, insurance, frieght (basically it is the import value)
The simiplified version of input table (Import) looks like this:
enter image description here
So from January to June the value 1 is assigned to SixMonthPeriod column, and the rest of the months are given the value 2.
I then want to calculate unit price for a six period, thus I use
select SixMonthPeriod, ProductDescrip, Sum(weight), Sum (CIF), (Sum (CIF))/(Sum(weight)) as UnitPrice
from Import
group by SixMonthPeriod, ProductDescrip;
This is fine, but I then want to calculate inflation for each product (over a six month period )where I need to use lag (an oracle analytical function). The six month period has to be fixed. Thus, if the previous period for a particular product is missing, then the unit price should be zero. I want to re-begin/begin the calculation of inflation for each product. The unit price and inflation equations looks like the following, respectively:
unit price = (Sum(weight) over a six month period)/(Sum (CIF) over a six month period)
inflation = (Current Unit price - previous unit price)/(previous unit price)
I use the following SQL to calculate inflation for a six month period for each product, where the calculation begins again for each product:
select Yr, SixMthPeriod, Product, UnitPrice, LagUnitPrice, ((UnitPrice -LagUnitPrice)/LagUnitPrice) as inflation
from (select Year as Yr, SixMonthPeriod as SixMthPeriod,
ProductDescrip as product, (Sum (CIF))/(Sum(weight)) as UnitPrice,
lag((Sum (CIF))/(Sum(weight)))
over (partition by ProductDescrip order by YEAR, SixMonthPeriod) as LagUnitPrice
From Import
group by Year, SixMonthPeriod, ProductDescrip)
The problem is the inflation period is not fixed.
For example, for the result, I get the following:
enter image description here
The first two rows are fine and there should be null values because they are my first line, thus there is no LagUnitPrice and inflation.
The third line has a problem where it has taken 0.34 as the LagUnitPrice but actually it is zero (for the period 2016 where SixMthPeriod=1 for the product barley). the oracle analytical functions does not take into account missing rows (e.g. for the period 2016 where SixMthPeriod=1 for the product barley).
how do I fix this problem (if you understand me)?
I have 96 rows, thus I can export the file to excel, and use excel's formulas to fix these exceptions.
You can autogenerate missing periods with nullable price, attach them to your data and do the rest as you did:
select product, year, smp, price, prev_price, (price - prev_price) / prev_price inflation
from (
select product, year, smp, price,
lag(price) over (partition by product order by year, smp) prev_price
from (
select year, ProductDescrip product, SixMonthPeriod smp, sum(CIF)/sum(weight) price
from Import
group by year, SixMonthPeriod, ProductDescrip) a
full join (
select distinct year, productdescrip product, column_value smp
from import cross join table(sys.odcinumberlist(1, 2))) b
using (product, year, smp))
order by product, year, smp
SQLFiddle demo
Subquery b is responsible for generating all periods, you can run it separately to see what it produces.
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').
I have a table Student which has name and ratings year wise.
Name Year Rating
Ram 2016 10
Sam 2016 9
Ram 2014 8
Sam 2012 7
I need to find the previous rating of the employee which could be last year or some years before.
The query should return below results
Name Cur_rating_year_2016 Prev_rating
Ram 10 8
Sam 9 7
Below is the script for insert and create
Create table Student (name varchar2(10), year number, rating number );
insert into student values('Ram' ,2016 ,10);
insert into student values('Sam' ,2016 ,9);
insert into student values('Sam' ,2012 ,7);
insert into student values('Ram' ,2014 ,8);
Is there a way to achieve this using select query?
Use LAG analytical function https://docs.oracle.com/database/122/SQLRF/LAG.htm#SQLRF00652
LAG is an analytic function. It provides access to more than one row
of a table at the same time without a self join. Given a series of
rows returned from a query and a position of the cursor, LAG provides
access to a row at a given physical offset prior to that position.
For the optional offset argument, specify an integer that is greater
than zero. If you do not specify offset, then its default is 1. The
optional default value is returned if the offset goes beyond the scope
of the window. If you do not specify default, then its default is
null.
SELECT stud_name AS name,
r_year AS year,
r_value AS rating,
lag(r_value, 1, NULL) OVER(PARTITION BY stud_name ORDER BY r_year) AS prev_rating
FROM stud_r
ORDER BY stud_name;
Try as:
SELECT A.NAME,A.RATING,B.RATING FROM
STUDENTS A INNER JOIN STUDENTS B
ON A.NAME=B.NAME
WHERE A.YEAR='2016' AND B.YEAR<>'2016'
ORDER BY A.NAME ASC
Using Oracle, PSQL, I am trying to figure out the earliest invoice date for each supplier. That would be simple enough, but I am also trying to figure out the max distribution line on the earliest invoice so I can determine what segment of the business the invoice belongs to. Segment is determined by SEGMENT_NUMBER in the example below. I know a sub query or multiple sub queries are needed here with a group by clause but I am at a loss. The syntax below is not even close, but I wanted to provided something for feedback.
SELECT
SUPPLIER_ID,
INVOICE_NUMBER,
SEGMENT_NUMBER,
MIN(INVOICE_DATE) as EARLIEST_INV_DATE,
MAX(DISTRIBUTION_AMOUNT) as MAX_DIST_LINE
FROM INVOICE_DIST
Use Analytical function like RANK().
SELECT SUPPLIER_ID,
INVOICE_NUMBER,
SEGMENT_NUMBER,
INVOICE_DATE,DISTRIBUTION_AMOUNT
(SELECT SUPPLIER_ID,
INVOICE_NUMBER,
SEGMENT_NUMBER,
INVOICE_DATE,DISTRIBUTION_AMOUNT,
RANK() OVER(PARTITION BY SUPPLIER_ID ORDER BY INVOICE_DATE,DISTRIBUTION_AMOUNT DESC) POSITION FROM INVOICE_DIST) TBL WHERE POSITION=1;