SQL Create Table by OrderID & Product Code between Ship & Return Date w Wkly Revenue - sql

Lo Folks o/
I apologize if I've titled this incorrectly or my terminology may be lacking as I am self-taught in writing SQL data queries; however, I am stuck on how to create one to produce data I need for a weekly rate of return review by product and order based on the orders' ship and return dates.
I have orders' line item detail to the product, qty, price etc. I am needing to group the data by the week start dates between the "ship" and "return" dates then calculate that week's revenue based on the line item's total over the number of weeks [and days in that week] the product is out.
I am also not sure if I even have the permissions to create a table, if that is necessary, nor where to begin to create this type of query.
Any help, direction or suggestions would be greatly appreciated.
Thanks all o/
My raw data looks like
And an excel view of my expected results

hmm ill take a stab - I am assuming you have an ORDERS o table (first image) and a RETURNS r table (second image). Also assuming you have the prodcode in your RETURNS table - maybe something like this:
WITH return_details as (
SELECT o.main_order, o.maincode, o.itemtotal,
r.ship_date, r.return_date,
DATE_TRUNC('WEEK', r.ship_date) as ship_week,
datediff(day, r.return_date, r.ship_date) as ship2return
FROM RETURNS r INNER JOIN ORDERS o ON
r.orderid = o.main_order AND r.prod_code = o.maincode
)
SELECT rd.main_order as order_id,
rd.maincode as prod_code,
rd.ship_week,
SUM(rd.itemtotal) as SUM_REVENUE,
SUM(rd.ship2return) as SUM_DAYSOUT,
AVG(rd.ship2return) as AVG_DAYSOUT
FROM return_details rd
GROUP BY order_id, prod_code, ship_week;

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;

Trying to figure out a solution to this question

Eliminating duplicate answers and mismatch in SQL
So the problem states that I need to find the transactions that happened each day and there is a mismatch between my answer on the correct answer and I don't know why!
this is a Short database description "Recycling firm"
The firm owns several buy-back centers for the collection of recyclable materials. Each of them receives funds to be paid to the recyclables suppliers. Data on funds received are recorded in the table
Income_o(point, date, inc)
The primary key is (point, date), where the point holds the identifier of the buy-back center, and the date corresponds to the calendar date the funds were received. The date column doesn’t include the time part, thus, money (inc) arrives no more than once a day for each center. Information on payments to the recyclables suppliers is held in the table
Outcome_o(point, date, out)
In this table, the primary key (point, date) ensures each buy-back center reports about payments (out) no more than once a day, too.
For the case income and expenditure may occur more than once a day, another database schema with tables having a primary key consisting of the single column code is used:
Income(code, point, date, inc)
Outcome(code, point, date, out)
Here, the date column doesn’t include the time part, either.
and The question is :
Under the assumption that receipts of money (inc) and payouts (out) can be registered any number of times a day for each collection point [i.e. the code column is the primary key], display a table with one corresponding row for each operating date of each collection point.
Result set: point, date, total payout per day (out), total money intake per day (inc).
Missing values are considered to be NULL.
SELECT Income.point, Income."date", SUM("out"), SUM(inc)
FROM Income left JOIN
Outcome ON Income.point = Outcome.point AND
Income."date" = Outcome."date"
GROUP BY Income.point, Income."date"
UNION
SELECT Outcome.point, Outcome."date", SUM("out"), SUM(inc)
FROM Outcome left JOIN
Income ON Income.point = Outcome.point AND
Income."date" = Outcome."date"
GROUP BY Outcome.point, Outcome."date";
My guess is that you have a bit of a Cartesian join by not including CODE as part of your join criteria. I think the following query should suit your needs:
WITH calendar AS
(
SELECT TRUNC(SYSDATE)-(LEVEL-1) AS DT
FROM DUAL
CONNECT BY LEVEL < 30
)
SELECT d.pnt AS "POINT",
c.dt AS "DATE",
d.outcome_total,
d.income_total
FROM calendar c
LEFT JOIN (SELECT nvl(inc.pnt, outc.pnt) AS PNT,
nvl(inc.dt, outc.dt) AS DT,
outc.amt AS OUTCOME_TOTAL,
inc.amt AS INCOME_TOTAL
FROM (SELECT i.pnt, i.dt, sum(i.inc) AS AMT
FROM income i
GROUP BY i.pnt, i.dt) inc
FULL JOIN (SELECT o.pnt, o.dt, sum(o.inc) AS AMT
FROM outcome o
GROUP BY o.pnt, o.dt) outc ON inc.pnt = outc.pnt AND inc.dt = outc.dt) d ON c.dt = d.dt;
I added the calendar table to account for the case where there was neither an income nor an outcome on a given day. However, if you don't need that, the query within the LEFT JOIN should be just fine.
N.B.: With the addition of the calendar WITH clause, this query will currently only show results from the last month(-ish). If you need longer, adjust the 30 day window.

SQL Difference Between Current Year and Last Year. If Last Year Data Does Not Exist Include Current Year

In a previous post I got help finding incremental sales. The query works great. I added the breakout by product. The issue I’m having is that I need to show new products being sold. If the product did not exist last year, but we are selling it this year; then it should show up in the data table.
I tried use a CASE statement in the WHERE, but it was causing a lot of duplication of the data. I was thinking something like what is below. How do I go about including items that are only in the current year? Thank you for your help, its greatly appreciated.
Not Working Where Clause
WHERE
Ym.Project =
CASE
WHEN ymprev.Project IS NULL THEN ym.Project
ELSE ymprev.Project
END
Below is the working query.
WITH ym as(
SELECT
Product
,SUM(Sales) AS Sales
,MONTH(Date) AS Month
,YEAR(Date) AS Year
FROM SalesTable
GROUP BY
YEAR(Date)
,MONTH(Date)
,Product
)
SELECT
ymprev.Project AS PrevProject
,ym.Product
,ym.Sales
,ymprev.Sales AS PreviousSales
,(ym.Sales - ymprev.Sales) AS IncrementalSales
,ymprev.Month AS PreviousMonth
,ymprev.Year AS PreviousYear
,ym.Month
,ym.Year
FROM ym
JOIN ym ymprev on
ymprev.Year = ym.Year
AND ymprev.Month = ym.Month
AND ymprev.Product = ym.Product
ORDER BY
ym.Year
,ym.Month
Your query is implicitly using an INNER JOIN - this means that you will only see values that have a match in both datasets, just as you describe.
Try changing your FROM clause to
FROM ym
LEFT JOIN
ym ymprev on
ymprev.Year = ym.Year
AND ymprev.Month = ym.Month
AND ymprev.Product = ym.Product
You will also need to incorporate similar logic in any values that include data elements from the previous year's query. For example, ,(ym.Sales - ymprev.Sales) AS IncrementalSales will need to be turned into ,(ym.Sales - ISNULL(ymprev.Sales,0)) AS IncrementalSales or it will return NULL for any records that only exist in the current year.
Your posted query doesn't include the Project field in your CTE, so I can't tell exactly how that works, but the posted data should get you started.

join two tables to get tomorrow's price (and the price two days from "now")

I'm trying to do a JOIN query to analyze some stocks. In my first table called top10perday, I list 10 stocks per day that I have chosen to "buy" the next day and sell the following day:
date symbol
07-Aug-08 PM
07-Aug-08 HNZ
07-Aug-08 KFT
07-Aug-08 MET
...
08-Aug-08 WYE
08-Aug-08 XOM
08-Aug-08 SGP
08-Aug-08 JNJ
For instance, for record #1:
the date of the record is 07-Aug-08
I want to buy a share of PM stock on the next trading day after 07-Aug-08 (which is 08-Aug-08)
I want to sell that shar eof PM stock two trading days after 07-Aug-08), which turns out to be 11-Aug-08
My stock prices are in a table called prices, which looks like this:
date symbol price
07-Aug-08 PM 54.64
08-Aug-08 PM 55.21
11-Aug-08 PM 55.75
12-Aug-08 PM 55.95
... many more records with trading day, symbol, price
I want to do a JOIN so that my result set looks like this:
date symbol price-next-day price-two-days
07-Aug-08 PM 55.21 55.75
...
list one record per date and symbol in table1.
I have tried doing something like:
SELECT top10perday.date, top10perday.symbol, Min(prices.date) AS MinOfdate
FROM prices INNER JOIN top10perday ON prices.symbol = top10perday.symbol
GROUP BY top10perday.date, top10perday.symbol
HAVING (((Min(prices.date))>[date]));
I have tried many variations of this, but I'm clearly not on the right path, because the result set just includes 10 rows as of the earliest date shown in my top10perday table.
I am using Microsoft Access. Thanks in advance for your help! :-)
This syntax worked in Access 2003:
SELECT t10.Date, t10.Symbol, p1.date, p1.price, p2.date, p2.price
FROM
(top10perday AS t10
LEFT JOIN prices AS p1
ON t10.Symbol = p1.symbol)
INNER JOIN prices AS p2 ON t10.Symbol = p2.symbol
WHERE (
((p1.date)=((Select Min([date]) as md
from prices
where [date]>t10.[Date] and symbol = t10.symbol
))
) AND ((p2.date)=((Select Min([date]) as md
from prices
where [date]>p1.[Date] and symbol = t10.symbol)
))
);
the idea is to get the first (min) date that is greater than the date in the previous table (top10perday and the prices as p1)
This should just be a join between three copies of the prices table. The problem is that you need to join to the next trading day, and that's a slightly trickier problem, since it's not always the next day. So we end up with a more complex situation (particularly as some days are skipped beacuse of holidays).
If it weren't Access you could use row_number() to order your prices by date (using a different sequence per stock code).
WITH OrderedPrices AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY symbol ORDER BY date) AS RowNum
FROM Prices
)
SELECT orig.*, next_day.price, two_days.price
FROM OrderedPrices orig
JOIN
OrderedPrices next_day
ON next_day.symbol = orig.symbol AND next_day.RowNum = orig.RowNum + 1
JOIN
OrderedPrices two_days
ON two_days.symbol = orig.symbol AND two_days.RowNum = orig.RowNum + 2
;
But you're using Access, so I don't think you have ROW_NUMBER().
Instead, you could have a table which lists the dates, having a TradingDayNumber... then use that to facilitate your join.
SELECT orig.*, next_day.price, two_days.price
FROM Prices orig
JOIN
TradingDays d0
ON d1.date = orig.date
JOIN
TradingDays d1
ON d1.TradingDayNum = d0.TradingDayNum + 1
JOIN
TradingDays d2
ON d2.TradingDayNum = d0.TradingDayNum + 2
JOIN
Prices next_day
ON next_day.symbol = orig.symbol AND next_day.date = d1.date
JOIN
Prices two_days
ON two_days.symbol = orig.symbol AND two_days.date = d2.date
But obviously you'll need to construct your TradingDays table...
Rob
My guess is:
SELECT top10perday.date, top10perday.symbol, MIN(pnd.price) AS PriceNextDay, MIN(ptd.price) AS PriceTwoDays
FROM top10perday
LEFT OUTER JOIN prices AS pnd ON (pnd.symbol = top10perday.symbol AND pnd.date > top10perday.date)
LEFT OUTER JOIN prices AS ptd ON (ptd.symbol = top10perday.symbol AND ptd.date > pnd.date)
GROUP BY top10perday.date, top10perday.symbol
HAVING ((pnd.date = Min(pnd.date) AND ptd.date = Min(ptd.date));
It´s just a shoot in the dark but my reasoning is: List all stocks you want (top10perday) and for each stock get the price, if exists, with mininum date after its date to populate the PriceNextDay and the price with minimun date after the PriceNextDay to populate the PriceTwoDays. The performance may stinks. But test it and see if it works. Later we can try to improve it.
**EDIT**ed to include Rob Farley´s comment.
I'm not a guru on this transformation but I can point you at an idea. Try using Pivot on the date column for each symbol in your query from a date to a date. This should give you a table with many columns with the name of the date you're using, and the price on each day. Indeed it should do this for every stock symbol you have over a given time.
Based on what you're trying to graph though, I think it would be interesting for you to look at the VWSP not just the spot price on your trades if you're trying to plot the stock performance.