Sum having a condition - sql

I've a table that has this information:
And need to get the following information:
If the country of the same person name (in this case Artur) is different, then I need to sum the two values of quantity from the max date (in this case 04/10) and return both person (Artur) and the qty (15k)
If the country of the same person name (in this case Joseph) is the same, then I need only the first row of the max date available.
I'm really struguling as I'm not sure how to implement the logic into my code:
Select
table.person,
table.quantity
From
(
Select
table.date,
table.person,
table.country,
table.quantity,
ROW_NUMBER () over (
PARTITION by table.code, table.person
ORDER by table.date DESC
) AS rn
FROM
table
WHERE table.date >= DATE '{2020-04-10}' -5
) a
WHERE a.RN IN (1,2)
Is it possible to create a rule to sum rows 1 and 2 when country is different (Artur case) and only return row number 1 when the country is the same for a name (Joseph case)?

Use dense_rank() or max() as a window function:
select person, sum(quantity)
from (select t.*,
max(date) over (partition by person) as max_date
from t
) t
where date = max_date
group by person;
EDIT:
Hmmm . . . I think you might want one row per country per person on the max date. If so:
select person, sum(quantity)
from (select t.*,
row_number() over (partition by person, country order by date desc) as seqnum_pc,
rank() over (partition by person order by date desc) as seqnum_p
from t
) t
where seqnum_p = 1 and seqnum_pc = 1
group by person;

Related

Get last record by month/year and id

I need to get the last record of each month/year for each id.
My table captures daily, for each id, an order value which is cumulative. So, I need that at the end I only have the last record of the month for each id.
I believe without something simple, but with the examples found I could not replicate for my case.
Here is an example of my input data and the expected result: db_fiddle.
My attempt doesn't include grouping by month and year:
select ar.id, ar.value, ar.aquisition_date
from table_views ar
inner join (
select id, max(aquisition_date) as last_aquisition_date_month
from table_views
group by id
)ld
on ar.id = ld.id and ar.aquisition_date = ld.last_aquisition_date_month
You could do this:
with tn as (
select
*,
row_number() over (partition by id, date_trunc('month', aquisition_date) order by aquisition_date desc) as rn
from table_views
)
select * from tn where rn = 1
The tn cte adds a row number that counts incrementally in descending order of date, for each month/id.. Then you take only those with rn=1, which is the last aquisition_date of any given month, for each id

How to write Bigquery for below table

The output should be count of max items sold in a date.
This is bigquery table:
item,date
apple,1-1-2020
apple,1-1-2020
pear,1-1-2020
pear,1-1-2020
pear,1-2-2020
pear,1-2-2020
pear,1-2-2020
orange,1-2-2020
Expected output:
item,date
apple,1-1-2020
pear,1-1-2020
pear,1-2-2020
Consider below approach
select item, date, count(1) sales
from `project.dataset.table`
group by item, date
qualify rank() over(partition by date order by sales desc) = 1
When applied to sample data in your question - output is
If for some reason, you don't want to have sales column in your output - use below
select item, date
from `project.dataset.table`
group by item, date
qualify rank() over(partition by date order by count(1) desc) = 1
if applied to sample data in your question - output is
The following query should do it:
SELECT
item,
sale_date,
FROM (
SELECT
sample.*,
COUNT(item) AS item_count
FROM
sample
GROUP BY
sample.sale_date,
item )
# Here you need to use a WHERE (or HAVING, or GROUP BY) in order to be able to use QUALIFY
WHERE sale_date IS NOT NULL
QUALIFY RANK() OVER(PARTITION BY sale_date ORDER BY item_count DESC) = 1

how to make a request?

I have a table Tabl1 : id, name, country, year, medal.
how can I find the top 10 countries by the number of medals for each year in 1 request?
thanks:)
You haven't told us anything about your table schema or the data, so this is a guess!
Going to assume your medal column contains the qty of medals for each Id/name, so you just need to rank by the sum of medals. Something along the lines of:
select [year], country, [Rank] from (
select [year], country, Rank() over(partition by [year] order by Sum(medal) desc ) [Rank]
from Tabl1
group by [year],country
)x
where [Rank]<=10
order by [year], [Rank]
here you can get the top 10 countries in each year:
select * from
(
select country,year,count(*),row_number() over (order by count(*) desc) as rn
from table
group by country, year
) tt
where tt.rn < 11
the sub query groups the data per country and year and gives you count() of each group, but at the same time It sorts them per count(*) desc and gives the a row number per each group ( it happanes using row_number() window funcion) , so the country with the most medal in eacg year is on top and it gets row number = 1 in each group , you need top 10 , so you filter them tt.rn < 11 in the main query.
If you want 10 countries per year:
with data as (
select country, "year" as yr,
rank() over (partition by "year" order by count(*) desc) as rnk
from T
group by country, "year"
)
select yr as "year", country from data
where rnk <= 10
order by yr, rnk;
Note that if ties are possible this could return more than ten rows for any given year.

Count customers the first time they appear

Hi I need to count the number of customers with subcategory=E grouped by seller (createdby). Once a customer has been counted by a seller, no other seller should be able to count that customer, eventhough a observation might exist.
Example
id customerID CreatedBy createdate subcategory
1 1111111111 EVAJEN 2014-03-14 E
2 1111111111 MICMAD 2014-04-15 E
3 9999999999 MICMAD 2014-02-10 E`
Here MICMAD shouldn't get a count for id=2 since EVAJEN already made a sale to that customer. Right now my code looks like this, but I'm not able to check if a customer already has been counted.
sel createdby, cast(createdate as date) as date1, count(distinct customerID)
from MyDatabase
where subcategory='E'
group by 1,2`
Thank you
You can use ROW_NUMBER to get one row per customer:
select createdby, cast(createdate as date) as date1, count(*)
from
(
select *
from tab
where subcategory = 'E'
qualify row_number() -- 1st row per customer
over (partition by customerId
order by createddate) = 1
) t
group by 1,2;
Use a subquery to get the first date and count that. In most databases (including Teradata), you can use window functions to get the first row for each customer:
select createdby, cast(createdate as date) as date1, count(*)
from (select t.*,
row_number() over (partition by customerId order by createddate asc) as seqnum
from MyDatabase t
where subcategory = 'E'
) t
where seqnum = 1
group by createdby, cast(createdate as date) ;

Ranking in Teradata- SQL

I am trying to rank my sales data using the rank() over function . Here is my code :
Select
Category as CAT
,units*cost as COST_SALES
,units*retail as RETAIL_COST
,units as UNITS_SOLD
,RANK() OVER (PARTITION BY 1 ORDER BY 3 DESC ) AS RANKING
from Table
Where date between current_date-7 and current_date
group by 1
When I get my result it is unordered and shows rank 1 for all the categories.
You can't use column references in the window functions. You need to name the columns explicitly:
Select Category as CAT, units*cost as COST_SALES, units*retail as RETAIL_COST,
units as UNITS_SOLD,
RANK() OVER (PARTITION BY Categroy ORDER BY units*retail DESC ) AS RANKING
from Table
Where date between current_date-7 and current_date
group by Category;