partition by based on a condition - sql

Table has customer, purchase date, item information
Need to populate first purchase date of "Item B" by any customer in a new column as "Min Purchase Date"
Try:
select
Customer ,
Purchase date,
Item
min(purchase date) over (partition by customer_id) as Min Purchase date
from table
where item = 'B'
Result
Expected result

Use a window function with conditional logic:
select t.*,
min(case when item = 'B' then purchasedate end) over (partition by customer)
from t;

Related

How to return first record and totalizers

How can I return first purchase date, first salesman and first store by customer along with his total expenses?
select
bi.biifclie as customer,
aux.salesman as first_salesman,
aux.store as first_store,
aux.date_ as first_date,
CAST(SUM(bi.biifpliq) as float64) as total_bought,
CAST((SUM(bi.biifptab)-SUM(bi.biifpliq)) as float64) as discount,
CAST(SUM(bi.biifpliq)-SUM(bi.biifcrep)-SUM(bi.biifvari + bi.biifcomb + bi.biifcomc + bi.biificmc)-SUM(bi.biiffixo) as float64) as rentability,
COUNT(DISTINCT bi.biifcodi) AS orders
MAX(bi.biifdata) AS last_purchase_date,
MIN(bi.biifdata) AS first_purchase_date,
DATE_DIFF(MAX(bi.biifdata),current_date(),month)*-1 as inactivity_time,
FROM yyyyyyy.gix.bi_biif bi
LEFT JOIN
(
SELECT
aux0.biifclie as customer,
aux0.biifvend as salesman,
aux0.biifempe as store,
aux0.biifdata as date_
FROM yyyyyyy.gix.bi_biif aux0 ORDER BY date_ ASC LIMIT 1
) AS aux ON aux.cliente = bi.biifclie
GROUP BY customer,first_salesman,first_store,first_date
I tried to do that using a left join sub query, ordering it by date (so that I can return the first date), but those fields (
aux.salesman as first_salesman,
aux.store as first_store,
aux.date_ as first_date,
)
all returned null
Am I doing smethng wrong or the logic is not correct?
Thanks!
Consider below
select biifclie as customer,
array_agg(struct(biifvend as salesman, biifempe as store, biifdata as date) order by biifdata limit 1)[offset(0)].*,
cast(sum(biifpliq) as float64) as total_bought
from `yyyyyyy.gix.bi_biif` t
group by customer
Above solution, does 1) grouping by customer 2) for each customer it takes all the respective rows and leaves the one - the first one ordered by date 3) than it "converts result from array to separate columns

PARTITION BY first use of a particular product

I'm trying to produce a table that lists the month, account and product name from our billing database. However, I also want to understand (for subsequent cohort analysis) what the earliest use is of "Product A" for each line item too. I was hoping I could do the following:
SELECT
Month,
AccountID,
ProductName,
SUM(NetRevenue) AS NetRevenue,
MIN(Month) OVER(PARTITION BY AccountID, 'Product A') AS EarliestUse
FROM
<<my-billing-table>>
WHERE
NetRevenue > 0
AND AccountID IN (
SELECT DISTINCT AccountID
FROM <<my-billing-table>>
WHERE ProductName = 'Product A' AND NetRevenue > 0
)
GROUP BY 1,2,3
...but it seems that just using "Product A" within the OVER clause does not have the desired effect (it seems to just return the first month for AccountID).
While the syntax is fine and the query runs, I'm obviously missing something regarding PARTITIONing the OVER clause. Any help much appreciated!
I think you want conditional aggregation along with a window function:
SELECT Month, AccountID, ProductName,
SUM(NetRevenue) AS NetRevenue,
MIN(MIN(CASE WHEN ProductName = 'Product A' THEN month END)) OVER (PARTITION BY AccountID) AS EarliestUse
FROM <<my-billing-table>>
WHERE NetRevenue > 0 AND
AccountID IN (SELECT AccountID
FROM <<my-billing-table>>
WHERE ProductName = 'Product A' AND NetRevenue > 0
)
GROUP BY 1,2,3;
The key expression here is an aggregation function nestled inside a window function. The aggregation function is MIN(CASE WHEN ProductName = 'Product A' THEN month END). This calculates the earliest month for the specified product on each row. This could be a column in the result set, and you would see the minimum value on the product row.
The window function then "spreads" this value over all rows for a given AccountID.
you are using a constant in partition it will not impact in your result, should use the column ProductName in partition to get the earliest use of the product
SELECT
Month,
AccountID,
ProductName,
SUM(NetRevenue) AS NetRevenue,
MIN(Month) OVER(PARTITION BY AccountID, ProductName) AS EarliestUse
FROM
<<my-billing-table>>
WHERE
NetRevenue > 0
AND AccountID IN (
SELECT DISTINCT AccountID
FROM <<my-billing-table>>
WHERE ProductName = 'Product A' AND NetRevenue > 0
)
GROUP BY 1,2,3

How to get the last sold price in SQL

I am working on a query that will show me basic item information as well as the total qty shipped (for all orders),last date that the item was sold and the price it was sold at. I cant figure out how to get the last sold price. This is what I have so far,
SELECT
item_id
,item_desc
,sum(qty_shipped) AS 'Total Qty Shipped'
,count(item_id) AS 'No of times Shipped'
,max(invoice_date) AS 'Last Invoice_date'
,unit_price AS 'Last Price'
FROM sales_history_report
WHERE
item_id = '1234'
AND year_for_period >= '2017'
AND sales_location_id like '10'
GROUP BY
item_id
,item_desc
,unit_price
with this query I am getting all of the lines that this item is on. It looks like this right now,
Item_id,Item_desc,Total_QTY_shipped,no_of_times_shipped,Last_Invoice_date,Last_price
1234,Item 1234,4,1,2014-10-15,2.47
1234,Item 1234,6,1,2014-09-20,2.519
But I am looking for
Item_id,Item_desc,Total_QTY_shipped,no_of_times_shipped,Last_Invoice_date,Last_price
1234,Item 1234,10,2,2014-10-15,2.47
Any help would be appreciated.
If I understand correctly, you can use conditional aggregation:
select item_id, item_desc,
sum(qty_shipped) as [Total Qty Shipped],
count(item_id) as [No of times Shipped],
max(invoice_date) as Max_Date,
max(case when seqnum = 1 then unit_price end) as [Last Price],
from (select shr.*,
row_number() over (partition by item_id order by invoice_date desc) as seqnum
from sales_history_report shr
) shr
where item_id = 1234 and
year_for_period >= 2017 and
sales_location_id like '10'
group by item_id, item_desc;
Comments:
Do not use single quotes for column aliases. Only use single quotes for string and date constants.
The columns in the GROUP BY define the rows in the result set. I don't think you want unit_price in it.
Do not use single quotes for numeric constants. I assume item_id an the year are numeric.

Working out total from sub total and amount

I have a table with purchased orders data.
Each row contails the amount of certain item purchased, cost per item and the order number group. Each different item purchased is a new row with same order number.
I basically want to return the total cost for that order. I have tried the following but am getting nowhere:
SELECT order_number, SUM( sub_total ) AS `total`
FROM
SELECT order_number, SUM( SUM( amount ) * SUM( cost_per_item ) ) AS `sub_total`
FROM `ecom_orders`
WHERE member_id = '4'
GROUP BY order_number
ORDER BY purchase_date DESC
Pretty much any SQL-92 compliant RDBMS will take this:
SELECT
order_number
,SUM(amount * cost_per_item) AS total
,purchase_date
FROM
ecom_orders
WHERE member_id = '4'
GROUP BY order_number,purchase_date
ORDER BY purchase_date DESC

Output two columns for 1 field for different date ranges?

I have a SQL table "ITM_SLS" with the following fields:
ITEM
DESCRIPTION
TRANSACTION #
DATE
QTY SOLD
I want to be able to output QTY SOLD for a one month value and a year to date value so that the output would look like this:
ITEM, DESCRIPTION, QTY SOLD MONTH, QTY SOLD YEAR TO DATE
Is this possible?
You could calculate the total quantity sold using group by in a subquery. For example
select a.Item, a.Description, b.MonthQty, c.YearQty
from (
select distinct Item, Description from TheTable
) a
left join (
select Item, sum(Qty) as MonthQty
from TheTable
where datediff(m,Date,getdate()) <= 1
group by Item
) b on a.Item = b.Item
left join (
select Item, sum(Qty) as YearQty
from TheTable
where datediff(y,Date,getdate()) <= 1
group by Item
) c on a.Item = c.Item
The method to limit the subquery to a particular date range differs per DBMS, this example uses the SQL Server datediff function.
Assuming the "one month" is last month...
select item
, description
, sum (case when trunc(transaction_date, 'MM')
= trunc(add_months(sysdate, -1), 'MM')
then qty_sold
else 0
end) as sold_month
, sum(qty_sold) as sold_ytd
from itm_sls
where transaction_date >= trunc(sysdate, 'yyyy')
group by item, description
/
This will give you an idea of what you can do:
select
ITEM,
DESCRIPTION,
QTY SOLD as MONTH,
( select sum(QTY SOLD)
from ITM_SLS
where ITEM = I.ITEM
AND YEAR = i.YEAR
) as YEAR TO DATE
from ITM_SLS I