Add values according to date - sql

I have the following table where I want the Quantity_Sold value to be added for an Item and a Customer if the item has been invoiced more than once in the same month. and I want to get this Sum of Quantity sold per month value in a separate column
Item Customer Invoice_Date Quantity_Sold
A XX 2014-11-04 00:00:00.000 13
A XX 2014-11-21 00:00:00.000 23
A XX 2014-12-19 00:00:00.000 209
A YY 2014-12-01 00:00:00.000 10
A YY 2014-12-22 00:00:00.000 6
B XX 2014-10-29 00:00:00.000 108
B YY 2014-11-06 00:00:00.000 70
B YY 2014-11-24 00:00:00.000 84
EX: XX has invoiced Item A twice in November so I'd want to get 36 (13+23) in a separate column.
So the result table I'd like is,
Item Customer Invoice_date Sum_Qty_Invoiced
A XX 2014-Nov 36
A XX 2014-Dec 209
A YY 2014-Dec 16
B XX 2014-Oct 108
B YY 2014-Nov 154
great if anyone could help me with this
Thanks

This is a simple group by with some string manipulation on the Invoice_Date column.
SELECT
Item,
Customer,
CAST(Year(Invoice_Date) AS VARCHAR(4)) + '-' + LEFT(DateName(m,Invoice_Date),3) AS Invoice_Date,
SUM(Quantity_Sold) AS Sum_Qty_Sold
FROM MyTable
GROUP BY Item,
Customer,
CAST(Year(Invoice_Date) AS VARCHAR(4)) + '-' + LEFT(Datename(m,Invoice_Date),3)
Live example: http://www.sqlfiddle.com/#!6/8fea75/3

You can achieve this by using DatePart and DateName functions of SQL Server.
SELECT Item
, Customer
, CONVERT (CHAR(4), DATEPART(YEAR, Invoice_date)) + '-' + CONVERT(CHAR(3), DATENAME(MONTH, Invoice_date)) AS Invoice_date
, SUM(Quantity_Sold) AS Sum_Qty_Invoiced
FROM [dbo].[Table1]
GROUP BY DATEPART(YEAR, Invoice_date), DATENAME(MONTH, Invoice_date), Item, Customer

Its a simple GroupBy clause. Just add group by on
Item,Customer,CAST(YEAR(Invoice_Date) AS Varchar(4))+'-'+LEFT(DATENAME(m,Invoice_Date),3)
Your query will be something like:
SELECT Item, Customer,
CAST(YEAR(Invoice_Date) AS Varchar(4)) +'-'+
LEFT(DATENAME(m,Invoice_Date),3)
AS Invoice_Date,SUM(Quantity_Sold)
AS Sum_Qty_Invoiced FROM TableName GROUP BY Item,Customer,
Item,Customer,CAST(YEAR(Invoice_Date) AS Varchar(4))+'-
'+LEFT(DATENAME(m,Invoice_Date),3)

Related

SQL Server : number of orders per date with day column

I have a query that pulls number of orders per date.
SELECT
name, CONVERT(VARCHAR(10), order_date, 120) AS order_date,
COUNT(1) AS orders
FROM
orders AS od
WHERE
id = 73
GROUP BY
CONVERT(VARCHAR(10), order_date, 120), name
ORDER BY
order_date, name
Below are the results I get when I run the query:
name order_date orders
--------------------------
20pmam 2016-07-27 39
20pmam 2016-07-28 30
20pmam 2016-07-29 32
20pmam 2016-07-31 468
20pmam 2016-08-02 75
20pmam 2016-07-05 30
I need my results to be like this, with a new column day
name order_date orders day
-------------------------------
20pmam 2016-07-27 39 1
20pmam 2016-07-28 30 2 // days between 2016-07-27 to 2016-07-28
20pmam 2016-07-29 32 3 // days between 2016-07-27 to 2016-07-29
20pmam 2016-07-31 468 5 // days between 2016-07-27 to 2016-07-31
20pmam 2016-08-02 75 7 // days between 2016-07-27 to 2016-08-02
20pmam 2016-08-05 30 10 // days between 2016-07-27 to 2016-08-05
The first/minimum order_date should be taken as day 1 ( in the above results 2016-07-27 is day 1) and should calculate others based on the first/minimum order_date.
Is this easily possible?
I don't have any idea how to get the desired result. I would appreciate any suggestions.
You can do this cross apply to get the minimum date before each order_date and use it in datediff.
SELECT name,CONVERT(VARCHAR(10), order_date, 120) AS order_date, Count(1) [orders],
1+coalesce(datediff(day,t.min_date,od.order_date),0) as [Day]
FROM orders AS od
cross apply (select min(od1.order_date) as min_date
from orders od1
where od.id=od1.id and od.name=od1.name and od1.order_date<od.order_date) t
WHERE id = 73
GROUP BY CONVERT(VARCHAR(10), order_date, 120),name,datediff(day,t.min_date,od.order_date)
ORDER BY order_date,name
Try something like:
SELECT name,
CONVERT(VARCHAR(10), order_date, 120) AS order_date,
Count(1) AS orders,
DATEDIFF(DAY, first_order_date, order_date) + 1
FROM orders AS od
JOIN (SELECT min(order_date) AS first_order_date
FROM orders) as fod ON 1 = 1
WHERE id = 73
GROUP BY CONVERT(VARCHAR(10), order_date, 120),
name,
DATEDIFF(DAY, first_order_date, order_date) + 1
ORDER BY order_date,
name
Hope this will solve your problem

Aggregate multiple columns based on specific date range with in a month

I need to aggregate Amounts to be displayed by date range per month. To illustrate please take a look at the following table:
Invoice_Payment
Customer_id Invoice_no Invoice_date Amount
---------------------------------------------------
10 10023 2016-07-08 60
10 10018 2016-08-04 90
11 10016 2016-07-01 110
11 10021 2016-07-05 120
12 10028 2016-07-11 10
12 10038 2016-07-31 5
As you'll notice, I want to group them based on Customer_id and display the dates from start to end. Furthermore, this has to be done for each month only.
Following query I have tried so far:
select Customer_id, (mindate + ' to ' + maxdate) Date_Range, Amount
from (
select Customer_id, sum(Amount) Amount, min(Invoice_date) mindate, max(Invoice_date) maxdate
from Invoice_Payment
group by Customer_id
) I ;
From above query I'm getting Output like:
Customer_id Date_Range Amount
10 2016-07-08 to 2016-08-04 150
11 2016-07-01 to 2016-07-05 230
12 2016-07-11 to 2016-07-31 15
Please check this.. SQL Fiddle Working Demo
Let's say Customer_id = 10 who has Invoice_date in July,2016 and August,2016. I need to sum up all payments of that particular Customer for the month of July and August separately within specific date range. But I am getting sum of Amount of all Invoice_date from above endeavor.
Desired output :
Customer_id Date_Range Amount
10 2016-07-08 to 2016-07-08 60
10 2016-08-04 to 2016-08-04 90
11 2016-07-01 to 2016-07-05 230
12 2016-07-11 to 2016-07-31 15
How could I get over this ? Any help would be greatly appreciated.
You are almost done. Just add YEAR and MONTH to GROUP BY.
select Customer_id, (mindate + ' to ' + maxdate) Date_Range, Amount
from (
select Customer_id,
sum(Amount) Amount, min(Invoice_date) mindate, max(Invoice_date) maxdate
from #Invoice_Payment
group by
Customer_id,
YEAR(Invoice_date),
MONTH(Invoice_date)
) I ;
How about grouping by customer_id, month and year
select Customer_id, (mindate + ' to ' + maxdate) Date_Range, Amount
from (
select Customer_id,
sum(Amount) Amount, min(Invoice_date) mindate, max(Invoice_date) maxdate
from #Invoice_Payment
group by Customer_id,month(Invoice_date), year(Invoice_date)
) I
order by customer_id;

Sum of sales by Quarter

How can i use SQL and SUM monthly data (quarter view)? I will not use Stored Procedures etc.
Current data:
ID | Sales
201601 | 5
201602 | 15
201603 | 5
201604 | 20
201605 | 8
201606 | 2
...
My ID column is like yyyymm
What I want is:
Quarter | Sales
Q1 | 25
Q2 | 30
....
You can try a query like below
SELECT
LEFT(ID,4) Year,
'Q'+ CAST((CAST(RIGHT(ID,2) AS INT)-1 )/3 +1 AS varchar) Quarter,
SUM(Sales) Sales
FROM
Yourtable
GROUP BY
LEFT(ID,4),
'Q'+ CAST((CAST(RIGHT(ID,2) AS INT) -1 )/3 +1 AS varchar)
order by year
SQL demo link
You can use DATEPART and QUARTER to get the quarter of a DATETIME. You just need to build the DATETIME using DATEFROMPARTS and parsing your ID column.
The CONCAT just adds 'Q' to the period number.
SELECT LEFT(id,4) [Year],
CONCAT('Q',DATEPART(QUARTER, DATEFROMPARTS(LEFT(id,4), RIGHT(id, 2), 1))) [Quarter],
SUM(Sales) [Sales]
FROM yourtable
GROUP BY LEFT(id,4), DATEPART(q, DATEFROMPARTS(LEFT(id,4), RIGHT(id, 2), 1))
ORDER BY [Year], [Quarter]

Get Invoice count of sales by stores for the last three months

This is my CustomerDetails table.
CustomerID CustCodeID
25 1
65 8
35 2
112 8
45 2
975 8
364 1
48 8
69 1
97 8
33 1
11 8
93 2
10 8
21 1
65 8
74 2
53 8
This is my Fact_SalesMetrics table.
Date Sales # CustomerID
2015-03-23 00:00:00.000 42895 25
2015-03-13 00:00:00.000 53920 53
2015-03-23 00:00:00.000 44895 65
2015-03-13 00:00:00.000 43920 35
2015-03-23 00:00:00.000 48895 112
2015-03-13 00:00:00.000 47920 45
2015-03-23 00:00:00.000 46895 975
2015-03-13 00:00:00.000 45920 48
2015-03-23 00:00:00.000 40895 69
2015-03-13 00:00:00.000 40920 11
2015-03-23 00:00:00.000 41895 33
2015-03-13 00:00:00.000 49920 21
......
I wish to make output like below:
CustCodeID March 2015
1 4
2 2
8 7
Which means the customer who has codeID '1' has 4 orders on March, 2 has 2 orders and like that.
To make this happen, I queried like below and got it working:
select CustCodeID,sum(March) as 'March 2015' from (
select bb.CustCodeID, aa.March from (
(SELECT count(distinct([Sales #])) as 'March', customerid
FROM [SalesData].[dbo].[Fact_SalesMetrics] a
where date >= '2015-03-01 00:00:00.000' and date <= '2015-03-31 00:00:00.000'
and customerid in (select customerid from CustomerDetails)
group by customerid ) as aa inner join (select customerid,CustCodeID from CustomerDetails ) as bb on aa.customerid=bb.customerid
)
) as dd group by CustCodeID
Now I wish to calculate the invoices count for the last three months like below:
CustCodeID March 2015 February 2015 January 2015
1 4 ? ?
2 2 ? ?
8 7 ? ?
Can anyone help me to achieve this?
Since you have column of type DateTime, you need to convert it to Month Year format. Use DateName in Sql Server to extract the monthname and year. You should then find the count of CustomerID and GROUP BY with the new date format and CustCodeID. You should use this query as the source query for the table to pivot.
If the values of months are known in advance, you can use Static Pivot by hard-coding the column names
SELECT CustCodeID,[March 2015],[February 2015],[January 2015]
FROM
(
SELECT CD.CustCodeID,COUNT(CD.CustomerID) COUNTOfCustomerID,
DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE]) MONTHS
FROM CustomerDetails CD
JOIN Fact_SalesMetrics FS ON CD.CustomerID=FS.CustomerID
GROUP BY CD.CustCodeID,DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE])
)TAB
PIVOT
(
MIN(COUNTOfCustomerID)
FOR MONTHS IN([March 2015],[February 2015],[January 2015])
)P
SQL FIDDLE
If the numbers of columns are not known in advance, you can go for Dynamic Pivot.
For that the first step is to get the column names to be displayed after pivot from the rows. In the following query, it will select the columns for the last 3 months.
DECLARE #cols NVARCHAR (MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(MONTHS)
FROM
(
SELECT TOP 3 DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE]) MONTHS
from Fact_SalesMetrics
GROUP BY '01 ' + DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE]),
DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE])
ORDER BY CAST('01 ' + DATENAME(MONTH,[DATE])+' ' + DATENAME(YEAR,[DATE]) AS DATE) DESC
) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
Now execute Pivot query using Dynamic sql
DECLARE #query NVARCHAR(MAX)
SET #query = '
SELECT * FROM
(
SELECT CD.CustCodeID,COUNT(CD.CustomerID) COUNTOfCustomerID,
DATENAME(MONTH,[DATE])+'' '' + DATENAME(YEAR,[DATE]) MONTHS
FROM CustomerDetails CD
JOIN Fact_SalesMetrics FS ON CD.CustomerID=FS.CustomerID
GROUP BY CD.CustCodeID,DATENAME(MONTH,[DATE])+'' '' + DATENAME(YEAR,[DATE])
) x
PIVOT
(
-- Specify the values to hold in pivoted column
MIN([COUNTOfCustomerID])
-- Get the column names from variable
FOR [MONTHS] IN('+#cols+')
) p
ORDER BY CustCodeID;'
EXEC SP_EXECUTESQL #query
SQL FIDDLE

Select sum of items based on their monthly entry date

I am trying to select sum of items based on their monthly entry date:
The Inventory table is as below:
EntryDate Items
1/1/2013 2
1/20/2013 5
1/23/2013 3
1/30/2013 2
2/4/2013 4
2/17/2013 34
The desired output with Total row added:
EntryDate Items
1/1/2013 2
1/20/2013 5
1/23/2013 3
1/30/2013 2
**Total 12**
2/4/2013 4
2/17/2013 34
**Total 38**
Below is my attempt. I am trying to do this using rollup but its counting all items at once and not by monthly basis, how to achieve this:
Select Convert(date, EntryDate) AS [DATE],SUM(Items) AS Total,
Case WHEN GROUPING(Items) = 1 THEN 'Rollup'
Else Status end AS Total From [Inventory] Group by Convert(date, EntryDate) WITH
Rollup
If you actually want results like your example, you can use the following:
SELECT EntryDate, Items
FROM (SELECT YEAR(EntryDate)'Year_',MONTH(EntryDate)'Month_',CAST(EntryDate AS VARCHAR(12))'EntryDate',Items,1 'sort'
FROM Inventory
UNION ALL
SELECT YEAR(EntryDate)'Year_',MONTH(EntryDate)'Month_','Total',SUM(Items)'Items',2 'sort'
FROM Inventory
GROUP BY YEAR(EntryDate),MONTH(EntryDate)
)sub
ORDER BY Year_,Month_,sort
Demo: SQL Fiddle
Try this, it will give you the month total in a new column, it will also work when your dates stretch over more than 1 year
SELECT EntryDate, Items,
SUM(Items) OVER (partition by dateadd(month, datediff(month, 0, entrydate), 0)) Total
FROM [Inventory]
Result:
EntryDate Items Total
2013-01-01 2 12
2013-01-20 5 12
2013-01-23 3 12
2013-01-30 2 12
2013-02-04 4 38
2013-02-17 34 38
DATEPART will do try this,
SELECT DATEPART(month, EntryDate) AS 'Month Number',sum(items1) FROM ITEMS
GROUP BY DATEPART(month, EntryDate)
# sqlfiddle
Try:
select entryDate, Items, sum(Items)
from (select entryDate,Items, to_date(entry_date, 'mm/yyyy') month_date from Inventory)
group by month_date
Here's a perfect solution for you
select isnull(cast(DATEFROMPARTS(year,month,day) as varchar),'Total'),
items
from ( SELECT datepart(yyyy,EntryDate) year,
DATEPART(mm, EntryDate) month,
DATEPART(dd, EntryDate) day,
sum(items) items
From Inventory
GROUP BY
ROLLUP (datepart(yyyy,EntryDate),
DATEPART(mm, EntryDate),
DATEPART(dd, EntryDate)
)
) a
where a.year is not null
and a.month is not null;
Demo HERE