How to join rows from the same table with different dates - sql

I am only a beginner in SQL and I am encountering the following problem:
I have a table with a list of SKU orders where each row displays the SKU, DELIVERY DATE, AND ORDER QUANTITY. I want to somehow rearrange the table in a way that the rows contain not only the delivery date for that given quantity, but also the following delivery date that occured in the future.
The table currently looks like that:
SKU/ DELIVERY_DATE/ QUANTITY_ORDERED
1.SKUx 14/3/2020 200
2.SKUx 19/3/2020 400
3.SKUx 27/3/2020 550
What I want to achieve is this:
SKU/ DELIVERY_DATE/ **NEXT_DELIVERY_DATE**/ QUANTITY_ORDERED <br/>
1.SKUx 14/3/2020 **19/3/2020** 200
2.SKUx 19/3/2020 **27/3/2020** 400
3.SKUx 27/3/2020 **NULL** 550
Keep in mind, as shown above, that the days between two deliveries vary (5 days between 14/3-19/3 and 8 days between 27/3-19/3) and therefore cannot pick an absolute value to make the column reappear twice e.g
SELECT SKU, DELIVERY_DATE,
DELIVERY_DATE + 5 AS NEXT_DELIVERY_DATE,
QUANTITY_ORDERED
FROM TABLE1
Any help is much appreciated!

Use lead():
select t1.*,
lead(delivery_date) over (partition by sku order by delivery_date) as next_delivery_date
from table1 t1

Related

Calculating the percentage of different types of customer feedback in each quarter

The problem statement is: I have a table (order_t) which has customer feedback (one column) and quarter number (as another column).
Using a CTE, I need to calculate the percentage of number of customer feedback in each category as well as the total number of customer feedback in each quarter.
After this happens, I need the percentage of different types of customer feedback (like good, bad, ok, very good, very bad) but using CTE.
How can I solve this statement?
I try to solve customer feedback as
WITH total_feedback AS
(
SELECT *
COUNT(CUSTOMER_FEEDBACK), QUARTER NUMBER
FROM
table1
GROUP BY
2
)
But I'm unable to calculate the first half portion, i.e. percentage of different types of customer feedback in each quarter using CTE.
How can I do that?
Find the file of the data
What you could do, and I'll keep the example as close to the code you provided as possible, is the following - using 2 CTE's:
WITH total_feedback AS (
SELECT COUNT(CUSTOMER_FEEDBACK) AS total_feedback, QUARTER_NUMBER
FROM table1
GROUP BY 2
),
category_feedback AS (
SELECT COUNT(CUSTOMER_FEEDBACK) AS feedback_count, CUSTOMER_FEEDBACK, QUARTER_NUMBER
FROM table1
GROUP BY 2, 3
)
SELECT
category_feedback.CUSTOMER_FEEDBACK,
category_feedback.QUARTER_NUMBER,
(feedback_count / total_feedback.total_feedback) * 100 AS feedback_percentage
FROM category_feedback
INNER JOIN total_feedback
ON category_feedback.QUARTER_NUMBER = total_feedback.QUARTER_NUMBER

I want NAV price as per (Today date minus 1) date

I have two tables. One is NAV where product daily new price is updated. Second is TDK table where item wise stock is available.
Now I want to get a summery report as per buyer name where all product wise total will come and from table one latest price will come.
I have tried below query...
SELECT dbo.TDK.buyer, dbo.NAV.Product_Name, sum(dbo.TDK.TD_UNITS) as Units, sum(dbo.TDK.TD_AMT) as 'Amount',dbo.NAV.NAValue
FROM dbo.TDK INNER JOIN
dbo.NAV
ON dbo.TDK.Products = dbo.NAV.Product_Name
group by dbo.TDK.buyer, dbo.NAV.Product_Name, dbo.NAV.NAValue
Imnportant: Common columns in both tables...
Table one NAV has column as Products
Table two TDK has column as Product_Name
If I have NAValue 4 records for one product then this query shows 4 lines with same total.
What I need??
I want this query to show only one line with latest NAValue price.
I want display one more line with Units*NAValue (latest) as "Latest Market Value".
Please guide.
What field contains the quote date? I am assuming you have a DATIME field, quoteDate, in dbo.NAV table and my other assumption is that you only store the Date part (i.e. mid-night, time = 00:00:00).
SELECT
t.buyer,
n.Product_Name,
sum(t.TD_UNITS) as Units,
sum(t.TD_AMT) as 'Amount',
n.NAValue
FROM dbo.TDK t
INNER JOIN dbo.NAV n
ON t.Products = n.Product_Name
AND n.quoteDate > getdate()-2
group by t.buyer, n.Product_Name, n.NAValue, n.QuoteDate
GetDate() will give you the current date and time. Subtracting 2 would get it before yesterday but after the day before yesterday.
Also, add n.quoteDate in your select and group by. Even though you don't need it, in case that one day you have a day of bad data with double record in NAV table, one with midnight time and another with 6 PM time.
Your code looks like SQL Server. I think you just want APPLY:
SELECT t.buyer, n.Product_Name, t.TD_UNITS as Units, t.TD_AMT as Amount, n.NAValue
FROM dbo.TDK t CROSS APPLY
(SELECT TOP (1) n.*
FROM dbo.NAV n
WHERE t.Products = n.Product_Name
ORDER BY ?? DESC -- however you define "latest"
) n;

Summing values based on values in other column (Variable)

I would like to sum all items within the query based on their ITEM, keep in mind this query is a daily report that will pick up different ITEM's depending on which items were purchased that day. Therefore, a basic CASE wont work.
For example:
ITEM_TABLE: expected result
Item Type Amount SUM
----------------------------------
SCARF 10 10
T-Shirt 20 45
T-Shirt 25 45
Current Query:
select SUM(AMOUNT)
from EDSREP.V_COGNOS_WSSTOR_SETTLE_RECON a
having CCY_CODE = a.CCY_CODE
Nothing is showing up, please help.
You can use window functions:
select
item_type,
amount,
sum(amount) over(partition by item_type) sum_amount
from item_table

Aggregated data from transactional table for sparklines

I'm working on an Ruby-on-Rails app which contains a list type of report. Two columns within that table are an aggregation from a transactional table.
So let's say we have these two tables:
**items**
id
name
group
price
**transactions**
id
item_id
type
date
qty
These two tables are connected with item_id in the transactions table.
Now I want to show some set of lines within the items table in a table and have two calculated columns within that table:
Calculated column 1 (Sparkline data):
Sparkline for transactions for the item with type="actuals" for the last 12 months. The result from the database should be text with aggregated qty for each month seperated by comma. Example:
15,20,0,12,44,33,6,4,33,23,11,65
Calculated column 2 (6m total sale):
Total qty for the item multiplied by sale for the last 6 months.
So the results would how columns like these:
Item name - Sparkline data - 6m total sale
So the result could by many thousand of lines, but would probably be paged.
So the question is, how is the most straightforward way of doing this in Rails models which doesn't sacrifice to much performance? Although this is a ruby-on-rails question it might contain more of a sql type solution.
The core sql could be something similar:
select
i.id,
i.name,
y.sparkline,
i.price*s.sum totalsale6m
from
items i left join
(select
x.item_id,
GROUP_CONCAT(x.sumqtd order by datemonth asc SEPARATOR ',') sparkline
from
(select
t.item_id,
date_format(date, '%m') datemonth,
sum(qtd) sumqtd
from
transactions t
where
t.type='actuals' and
t.date>date_sub(now(), interval 1 year)
group by
t.item_id, datemonth
) x
group by
x.item_id
) y on i.id=y.item_id
left join
(select
t.item_id,
sum(qtd) sumqtd
from
transactions t
where
t.date>date_sub(now(), interval 6 month)
group by
t.item_id
) s on i.id=s.item_id
group by
i.id, i.name
A few comments:
I wasn't able to test it without real data.
If there are gaps in the sales, I mean no sales in a given month, then the list will not contain 12 elements. In this case you need to adjust x,y tables
If you need the result only for a given few items, then probably you can put the item id filter deeper into the subqueries sparing time.

analyze range and if true tell me

I want to see if the price of a stock has changed by 5% this week. I have data that captures the price everyday. I can get the rows from the last 7 days by doing the following:
select price from data where date(capture_timestamp)>date(current_timestamp)-7;
But then how do I analyze that and see if the price has increased or decreased 5%? Is it possible to do all this with one sql statement? I would like to be able to then insert any results of it into a new table but I just want to focus on it printing out in the shell first.
Thanks.
It seems odd to have only one stock in a table called data. What you need to do is bring the two rows together for last week's and today's values, as in the following query:
select d.price
from data d cross join
data dprev
where cast(d.capture_timestamp as date = date(current_timestamp) and
cast(dprev.capture_timestamp as date) )= cast(current_timestamp as date)-7 and
d.price > dprev.price * 1.05
If the data table contains the stock ticker, the cross join would be an equijoin.
You may be able to use query from the following subquery for whatever calculations you want to do. This is assuming one record per day. The 7 preceding rows is literal.
SELECT ticker, price, capture_ts
,MIN(price) OVER (PARTITION BY ticker ORDER BY capture_ts ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS min_prev_7_records
,MAX(price) OVER (PARTITION BY ticker ORDER BY capture_ts ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS max_prev_7_records
FROM data