SQL Get Weekly Count of product items - sql

I am trying to get the total number entries into a table per week per product. Every time someone orders a product, it is entered into a database with the following information:
Table: Orders
order_id
order
order_date
There are 8 options for "order", which are pre-set and are never changing. I need to see the count per week of the items that are in that table..
I want to see something like this:
Order week 1 week 2 week 3 week 4 etc...
order1 30 10 11 23
order2 40 4 0 44
order3 88 23 12 22
Can someone tell me how that is achieved??
Thanks.. I'm so stuck on this.

as NickyvV indicated you want a pivot. However SQL Server cannot accept dynamic columns in a pivot, so you have to spell them out. Also you probably don't want the order_id in the first column, since you would only get 1s and 0s in the counts, but something like the product_id instead. So you could do something like this:
SELECT
product_id,
[week 1],[week 2],[week 3],[week 4],[week 5]
FROM
(SELECT
product_id,
'week ' + cast(DatePart(wk,[order_date]) as varchar(2)) as WeekName
FROM [Orders]) as o
pivot (count(WeekName)
for WeekName in ([week 1],[week 2],[week 3],[week 4],[week 5])) as p
Unfortunately, you'll have to spell out all possible week names. There would be ways using dynamic SQL, but i wouldn't recommend them as they are rather complex and nasty. Also, remember that if this is going into a report, you normally would do this pivoting in the reporting application (SSRS, etc.) instead of in the db.

Related

How do I average the last 6 months of sales within SQL based on period AND year?

How do I average the last 6 months of sales within SQL?
Here are my tables and fields:
IM_ItemWhseHistoryByPeriod.FISCALCALPERIOD,
IM_ItemWhseHistoryByPeriod.FISCALCALYEAR,
And I need to average these fields
IM_ItemWhseHistoryByPeriod.DOLLARSSOLD,
IM_ItemWhseHistoryByPeriod.QUANTITYSOLD,
The hard part I'm having is understanding how to average the last whole 6 months, ie. fsicalcalperiod 2-6(inside fiscalcalyear 2017).
I'm hoping for some help on what the SQL command text should look like since I'm very new to manipulating SQL outside of the UI.
Sample Data
My Existing SQL String:
SELECT IM_ItemWhseHistoryByPeriod.ITEMCODE,
IM_ItemWhseHistoryByPeriod.DOLLARSSOLD,
IM_ItemWhseHistoryByPeriod.QUANTITYSOLD,
IM_ItemWhseHistoryByPeriod.FISCALCALPERIOD,
IM_ItemWhseHistoryByPeriod.FISCALCALYEAR
FROM MAS_AME.dbo.IM_ItemWhseHistoryByPeriod
IM_ItemWhseHistoryByPeriod
ScaisEdge Attempt #1
if fiscalyear and fiscalperiod are number you could use
select avg(IM_ItemWhseHistoryByPeriod.DOLLARSSOLD) ,
avg(IM_ItemWhseHistoryByPeriod.QUANTITYSOLD)
from my_table
where IM_ItemWhseHistoryByPeriod.FISCALCALYEAR = 2017
and IM_ItemWhseHistoryByPeriod.FISCALCALPERIOD between 2 and 6
or for each item code
select itemcode, avg(IM_ItemWhseHistoryByPeriod.DOLLARSSOLD) ,
avg(IM_ItemWhseHistoryByPeriod.QUANTITYSOLD)
from my_table
where IM_ItemWhseHistoryByPeriod.FISCALCALYEAR = 2017
and IM_ItemWhseHistoryByPeriod.FISCALCALPERIOD between 2 and 6
group by itemcode
Try the following solution and see if it works for you:
select avg(DOLLARSSOLD) as AvgDollarSod,
avg(QUANTITYSOLD) as AvgQtySold
from IM_ItemWhseHistoryByPeriod
where FISCALCALYEAR = '2017
and FISCALCALPERIOD between 2 and 6

Conditional Sum SQL

I am very new to SQL and have been presented with, what seems to me, a complex task. I have a table which is generating the number of various fruit purchased on a given day. Thus:
G. A G.B
2016-06-01 Banana 45 0
2016-06-01 Pear 158 0
2016-06-01 apple 0 23
.... dates continue
I need to develop some kind of conditional sum to count how many types of fruit are bought with a specific grade on a specific date. So in the above case on the given date (2016-06-01) there would be 203 Grade A (G.A) bits of fruit and 23 Grade B (G.B) pieces of fruit.
Naturally some kind of
Sum(case when date=date then Grade else 0 ).
But, I am really baffled here. Please, any help would be greatly appreciated!!!!
A simple group clause should do the job here (Note: untested code)
select date, sum(grade_a) as grade_a_sum, sum(grade_b) as grade_b_sum
from sales
group by date;
This will give the grades for every date. Individual dates can then be selected if necessary.
Won't simple group by do the work..
Select
date,
sum(GA) as GA,
sum(GB) as GB
from
Table
group by date

In SQL Server, how can I duplicate my current set of results for each month and increase them by 1.5*

EDIT: I updated this post cause I had to change my table, I had to change my Quantity from an INT to varchar to accommodate for decimals and now the below answers won't work, is varchar the best option for this?
Sorry, this might be a bit of a simple question for someone who knows what they're doing but I'm super new to SQL.
I've created this table (60 results in total)
However these are just the results for the first month of the year (January)
all further results are the same except the quantity is a 1.5% increase per month, so in February (2016-02-01) the first employee's six quantity's would be
111
165
463
156
99
63
However I'm having trouble getting my head around using scripts to enter results. I could manually enter each month but that would take me quite a few hours as there's 60 results for each month. So I was thinking maybe I could copy the current contents of the table into a temporary variable then create some sort of loop that has a 1.5% increase for each month and also changes the date to the relevant month, but I have absolutely no idea how to go about doing this.
If anyone could help me out with how I could go about doing this I'd be super grateful, I'm so stumped and I don't even know where to start
You can add the next month by doing:
insert into t(employee_id, month, product_id, quantity)
select employee_id, dateadd(month, 1, [month]), product_id, quantity*(1 + 0.015)
from t
where t.[month] = '2016-01-01';
I would recommend that you just repeat this 11 times, changing the where clause each time. You can set up a query to do all 11 months at the same time, but it is probably not worth the effort.
You can do an INSERT/SELECT where your table is both source and target:
INSERT INTO tab
SELECT Sale_ID, Employee_ID, dateadd(month, 1, [Month]), Product_ID, Quantity * 1.015
FROM tab
WHERE [Month] = '2016-01-01'
Repeat this for 10 times and increase the number of months by one in each repetiton.
To do the inserts for all month in a single query you could add a CROSS JOIN to a series of numbers from 1 to 11:
INSERT INTO tab
SELECT Sale_ID, Employee_ID, dateadd(month, numbers.n, [Month]), Product_ID, Quantity * 1.015
FROM tab CROSS JOIN (select sale_ID AS n from tab where sale_ID between 1 and 11) AS numbers
WHERE [Month] = '2016-01-01'

SQL Percentile function missing?

It is a mystery to me with this text book example. We have simply:
Transaction_ID (primary key), Client_ID, Transaction_Amount, Month
1 1 500 1
2 1 1000 1
3 1 10 2
4 2 11 2
5 3 300 2
6 3 10 2
... ... ... ...
I want to calculate in SQL the mean(Transaction_Amount), std(Transaction_Amount) and the some percentile(Transaction amount) grouped by Client_ID. But is seems, even given that percentile is a very similar calculation than the standard deviation, SQL cannot do it with a simple statement as:
SELECT
mean(Transaction_Amount),
std(Transaction_Amount),
percentile(Transaction_Amount)
FROM
myTable
GROUP BY
Client_ID, Month
Or can it?
It gets worse becuase I also need to Group By Month in addition to Client_ID.
Thanks a lot!
Sven
I'm sure Oracle can do the calculations you want. I just don't know what they are. You specify that you want something grouped by ClientId. Yet, your sample query has two keys in the GROUP BY.
Some functions that you want to look at are:
AVG()
STDDEV()
PERCENT_RANK()
Without sample data and desired results (or a very clear explanation of what you are trying to calculate), I can't put together a query.

Group By with Case statement?

I need find the number Sum of orders over a 3 day range. so imagine a table like this
Order Date
300 1/5/2015
200 1/6/2015
150 1/7/2015
250 1/5/2015
400 1/4/2015
350 1/3/2015
50 1/2/2015
100 1/8/2015
So I want to create a Group by Clause that Groups anything with a date that has the same Month, Year and a Day from 1-3 or 4-6, 7-9 and so on until I reach 30 days.
It seems like what I would want to do is create a case for the grouping that includes a loop of some type but I am not sure if this is the best way or if it is even possible to combine them.
An alternative might be create a case statement that creates a new column that assigns group number and then grouping by that number, month, and Year.
Unfortunately I've never used a case statement so I am not sure which method is best or how to execute them especially with a loop.
EDIT: I am using Access so it looks like I will be using IIF instead of Case
Consider the Partition Function and a crosstab, so, for example:
TRANSFORM Sum(Calendar.Order) AS SumOfOrder
SELECT Month([CalDate]) AS TheMonth, Partition(Day([Caldate]),1,31,3) AS DayGroup
FROM Calendar
GROUP BY Month([CalDate]), Partition(Day([Caldate]),1,31,3)
PIVOT Year([CalDate]);
As an aside, I hope you have not named a field / column as Date.
How about the following:
COUNT OF ORDERS
select year([Date]) as yr,
month([Date]) as monthofyr,
sum(iif((day([Date])>=1) and (day([Date])<=3),1,0)) as days1to3,
sum(iif((day([Date])>=4) and (day([Date])<=6),1,0)) as days4to6,
sum(iif((day([Date])>=7) and (day([Date])<=9),1,0)) as days7to9,
sum(iif((day([Date])>=10) and (day([Date])<=12),1,0)) as days10to12,
sum(iif((day([Date])>=13) and (day([Date])<=15),1,0)) as days13to15,
sum(iif((day([Date])>=16) and (day([Date])<=18),1,0)) as days16to18,
sum(iif((day([Date])>=19) and (day([Date])<=21),1,0)) as days19to21,
sum(iif((day([Date])>=22) and (day([Date])<=24),1,0)) as days22to24,
sum(iif((day([Date])>=25) and (day([Date])<=27),1,0)) as days25to27,
sum(iif((day([Date])>=28) and (day([Date])<=31),1,0)) as days28to31
from tbl
where [Date] between x and y
group by year([Date]),
month([Date])
Replace x and y with your date range.
The last group is days 28 to 31 of the month, so it may contain 4 days' worth of orders, for months that have 31 days.
THE ABOVE IS A COUNT OF ORDERS.
If you want the SUM of the order amounts:
SUM OF ORDER AMOUNTS
select year([Date]) as yr,
month([Date]) as monthofyr,
sum(iif((day([Date])>=1) and (day([Date])<=3),order,0)) as days1to3,
sum(iif((day([Date])>=4) and (day([Date])<=6),order,0)) as days4to6,
sum(iif((day([Date])>=7) and (day([Date])<=9),order,0)) as days7to9,
sum(iif((day([Date])>=10) and (day([Date])<=12),order,0)) as days10to12,
sum(iif((day([Date])>=13) and (day([Date])<=15),order,0)) as days13to15,
sum(iif((day([Date])>=16) and (day([Date])<=18),order,0)) as days16to18,
sum(iif((day([Date])>=19) and (day([Date])<=21),order,0)) as days19to21,
sum(iif((day([Date])>=22) and (day([Date])<=24),order,0)) as days22to24,
sum(iif((day([Date])>=25) and (day([Date])<=27),order,0)) as days25to27,
sum(iif((day([Date])>=28) and (day([Date])<=31),order,0)) as days28to31
from tbl
where [Date] between x and y
group by year([Date]),
month([Date])