I want to join my CHEESE table with FRESHNESS to get CHEESE and FRESHNESS code for
cheeses where max(seq_no) for each cheese id is MOLD.
When using rank(), where do I join to FRESHNESS?
CHEESE FRESHNESS
CHEESE_ID SEQ_NO FRESH_CODE FRESH_CODE FRESH_DESC
================================= ========================
1 1 MOLD MOLD MOLDY CHEESE
1 23 FRSH FRSH EDIBLE
1 34 FRSH
2 2 FRSH
2 18 MOLD
3 3 MOLD
3 5 MOLD
3 7 MOLD
DESIRED RESULT
==========================
CHEESE_ID SEQ_NO FRESH_CODE FRESH_DESC SEQ_RANK
2 18 MOLD MOLDY CHEESE 1
3 7 MOLD MOLDY CHEESE 1
Here's my code I'm using to get the desired sequence numbers.
select
cheese_id,seq_no,fresh_code,seq_rank
from ( select
cheese_id,seq_no, fresh_code,
rank() over (partition by cheese_id
order by seq_no desc) seq_rank
from cheese
where seq_rank = 1
and fresh_code = 'MOLD'
You can either do the join in the subquery
select cheese_id,seq_no,fresh_code,fresh_desc,seq_rank
from ( select cheese_id,
seq_no,
fresh_code,
fresh_desc,
rank() over (partition by cheese_id
order by seq_no desc) seq_rank
from cheese
join freshness using (fresh_code) )
where seq_rank = 1
and fresh_code = 'MOLD'
or you can join to your subquery
select cheese_id,seq_no,fresh_code,fresh_desc,seq_rank
from ( select cheese_id,
seq_no,
fresh_code,
fresh_desc,
rank() over (partition by cheese_id
order by seq_no desc) seq_rank
from cheese ) cheese_outer
join freshness using (fresh_code)
where seq_rank = 1
and fresh_code = 'MOLD'
Related
In PL SQL is there a way to produce the Order Count per customer as follows... Thanks for your help.
Cust Order# Order Count
ABC1 011 1
ABC1 052 2
ABC1 199 3
BBA1 150 1
BBA1 158 2
Thanks
Gavin
If I understood you correctly, a little bit of analytics might do the job. Here's an example:
SQL> with test (cust, order#) as
2 (select 'ABC1', '011' from dual union all
3 select 'ABC1', '052' from dual union all
4 select 'ABC1', '199' from dual union all
5 select 'BBA1', '150' from dual union all
6 select 'BBA1', '158' from dual
7 )
8 select cust, order#,
9 row_number() over (partition by cust order by order#) order_count
10 from test;
CUST ORD ORDER_COUNT
---- --- -----------
ABC1 011 1
ABC1 052 2
ABC1 199 3
BBA1 150 1
BBA1 158 2
SQL>
sounds like you want a GROUP BY such as
select cust, SUM(order_count)
from MyTable
group by cust;
which should yield
cust SUM
ABC1 6
BBA1 3
I am new to PL/SQL
I have a code like this
SELECT f.code,f.date,f.amt, row_number() OVER (PARTITION BY f.code ORDER BY f.date DESC) ranki
FROM advance.alloc f
and shows
CODE DATE AMT ranki
122 12/31/2016 3 1
122 12/31/2015 7 2
122 12/31/2014 3 3
123 6/30/2015 3 1
125 6/30/2015 2 1
125 12/31/2014 8 2
Logic is this
if DATE = 12/__/__ AND ranki = 1 THEN ranki 1, so 122 picks 12/31/2016 3
if DATE = 6/30/__ AND ranki = 1 AND if ranki = 2 exists THEN then pick the second one,so 125 picks 12/31/2014 8
if 6/30__ and ranki is ONLY 1 shows Blank on date LIKE 123
so I would like to show
122 12/31/2016 3
123 __________ 3
125 12/31/2014 8
How can I code like this PL/SQL?
WHEN to_char(af.date,'MM') = 12 AND af.ranki = 1 THEN af.date END
I could code first logic, but I can not figure out how to code the rest of the logic
Thanks
Why in PL/SQL? Or do you mean "in Oracle SQL"? (The solution below uses standard analytic functions, so it is not specific to Oracle.)
Add more information through analytic functions, in addition to ranki. Extract the month from the row with ranki = 1, and also the total count for each code. Then the WHERE clause can follow your logic step by step.
with
f ( code, dt, amount ) as (
select 122, to_date('12/31/2016', 'mm/dd/yyyy'), 3 from dual union all
select 122, to_date('12/31/2015', 'mm/dd/yyyy'), 7 from dual union all
select 122, to_date('12/31/2014', 'mm/dd/yyyy'), 3 from dual union all
select 123, to_date( '6/30/2015', 'mm/dd/yyyy'), 3 from dual union all
select 125, to_date( '6/30/2015', 'mm/dd/yyyy'), 2 from dual union all
select 125, to_date('12/31/2014', 'mm/dd/yyyy'), 8 from dual
)
-- End of simulated data (for testing purposes only, not part of the solution).
-- SQL query begins BELOW THIS LINE.
select code, case when mth = 12 or ranki = 2 then dt end as dt, amount
from ( select code, dt, amount,
first_value(extract (month from dt))
over (partition by code order by dt desc) as mth,
row_number() over (partition by code order by dt desc) as ranki,
count(*) over (partition by code) as cnt
from f
)
where mth = 12 and ranki = 1
or cnt = 1
or mth = 6 and ranki = 2
;
CODE DT AMOUNT
---- ---------- ------
122 12/31/2016 3
123 3
125 12/31/2014 8
I want to group by lead function by two column. Here is my table data.
Id Name_Id Name Item_Id Item_Name date
1 1 Car 1 SUV 1-Jan-2015
2 1 Car 1 SUV 12-March-2015
3 1 Car 1 SUV 20-April-2015
4 1 Car 2 Sport 23-April-2015
5 2 Bike 1 SUV 18-July-2015
6 2 Bike 1 SUV 20-Aug-2015
7 2 Bike 2 Sport 18-Sept-2015
8 2 Bike 3 Honda 20-OCT-2015
And I need result from above table like.
Id Name_Id Name Item_Id Item_Name start date end date
1 1 Car 1 SUV 1-Jan-2015 20-April-2015
2 1 Car 2 Sport 20-April-2015 23-April-2015
3 2 Bike 1 SUV 18-July-2015 20-Aug-2015
4 2 Bike 2 Sport 20-Aug-2015 18-Sept-2015
5 2 Bike 3 Honda 18-Sept-2015 20-OCT-2015
Any suggestion really appreciated.
I don't think you need to use LEAD here. The CTE below computes, for each Item_Id, the earliest and latest date. This is then joined to your original table to restrict to records corresponding to the earliest Item_Id. At the same time, the end date is also pulled in during the join.
WITH cte AS (
SELECT Name,
Item_Id,
MIN(date) AS start_date,
MAX(date) AS end_date
FROM yourTable
GROUP BY Name, Item_Id
)
SELECT t1.Id, t1.Name_Id, t1.Name, t1.Item_Id, t1.Item_Name,
t2.start_date,
t2.end_date
FROM yourTable t1
INNER JOIN cte t2
ON t1.Item_Id = t2.Item_Id AND
t1.Name = t2.Name AND
t1.date = t2.start_date
This is how I have a sample table in SQLITE
ID NAME AGE ADDRESS SALARY
1 Paul 32 California 20000.0
2 Allen 25 Texas 15000.0
3 Teddy 23 Norway 20000.0
4 Mark 25 Rich-Mond 65000.0
5 David 27 Texas 85000.0
6 Kim 22 South-Hall 45000.0
7 Paul 32 California 20000.0
8 Allen 25 Texas 15000.0
9 Teddy 23 Norway 20000.0
What I want to achieve is a join on my SQLITE table on these two queries
select AGE, count(*) as SALARYLESSTHAN45 from company where salary < 45000 group by salary
select AGE, count(*) as SALARYMORETHAN45 from company where salary > 45000 group by salary
I tried the following
select AGE, count(*) as SALARYLESSTHAN45 from company where salary < 45000 group by salary ) T1
INNER JOIN
select AGE, count(*) as SALARYMORETHAN45 from company where salary > 45000 group by salary ) T2
ON T1.AGE = T2.AGE
but cannot get this to work...
Can someone share an example of how to achieve this in SQLITE ?
A join on two different tables would look like this:
SELECT ... FROM Tab1 JOIN Tab2 ON ...
To do the join on the result of a query, you have to replace the table name with a subquery:
select AGE,
SALARYLESSTHAN45,
SALARYMORETHAN45
from (select AGE,
count(*) as SALARYLESSTHAN45
from company
where salary < 45000
group by salary)
join (select AGE,
count(*) as SALARYMORETHAN45
from company
where salary > 45000
group by salary)
using (AGE);
Here is the code (simulating full outer join for sqlite3):
SELECT EMP_ID, ID, NAME, DEPT FROM COMPANY LEFT OUTER JOIN DEPARTMENT ON COMPANY.ID = DEPARTMENT.EMP_ID
union
SELECT EMP_ID, ID, NAME, DEPT FROM department LEFT OUTER JOIN company ON COMPANY.ID = DEPARTMENT.EMP_ID
The company table has the columns: id, name, age, address, salary.
The department table has the columns: id, dept, emp_id.
The problem is that both tables have the id column, but I only want to select the id column from company. How can I do this?
Solved by using an alias:
SELECT EMP_ID, c.id, NAME, DEPT FROM COMPANY as c LEFT OUTER JOIN DEPARTMENT as d ON c.ID = d.EMP_ID
union
SELECT EMP_ID, c.id, NAME, DEPT FROM department as d LEFT OUTER JOIN company as c ON c.ID = d.EMP_ID;
This nicely illustrate the result of a full outer join:
3 Teddy
4 Mark
5 David
6 Kim
7 James
8 Kitos
9 Paul
10 James
11 James
12 James
13 James
14 James
15 James
16 James
17 James
1 1 Paul IT Billing
2 2 Allen Engineering
77 Finance
Blank cells are null.