SQL: Create Multiple Selects Based One Date - sql

I've been searching for help on this but I can't seem to find the solution. What I have is:
Table called Details_Orders.
Columns: CustomerName, InvoiceDate, SaleAmount and SaleCost.
What I want to do is select a date ('1-1-2015') and display the Customer Name, the Date ('1-1-2015'), the sum of SaleAmount for that Date, and the Sum of the SaleCost. And here's the part I'm having problems with, I want the next columns to display the previous months SaleAmount and SaleCost, then the previous YEARS SaleAmount and SaleCost.
I'm having trouble figuring out how to code the Previous Time Periods Select statements. Any help on this would be greatly appreciated.
Select
CustomerName,
InvoiceDate,
Sum(SaleAmount),
Sum(SaleCost),
*PREVIOUS MONTH Sum(SalesAmount) DATEADD(MONTH,-1,'1-1'2015'),
PREVIOUS MONTH Sum(SalesCost) DATEADD(MONTH,-1,'1-1'2015'),
PREVIOUS YEAR Sum(SalesAmount) DATEADD(YEAR,-1,'1-1'2015'),
PREVIOUS YEAR Sum(SalesCost) DATEADD(YEAR,-1,'1-1'2015')*
From Details_Orders
WHERE InvoiceDate='1-1-2015'
Basic

You want to use conditional aggregation, and also need a group by. It is a bit unclear what the exact definitions of previous month and year are. Here is one interpretation:
Select CustomerName,
Sum(case when InvoiceDate = thedate then SaleAmount else 0 end),
Sum(case when InvoiceDate = thedate then SaleCost else 0 end),
Sum(case when year(InvoiceDate)*12 + month(InvoiceDate) =
year(thedate)*12 + month(thedate) - 1
then SaleAmount else 0
end),
Sum(case when year(InvoiceDate)*12 + month(InvoiceDate) =
year(thedate)*12 + month(thedate) - 1
then SaleCost else 0
end),
Sum(case when InvoiceDate < thedate and
InvoiceDate >= dateadd(year, -1, thedate
then SaleAmount else 0
end),
Sum(case when InvoiceDate < thedate and
InvoiceDate >= dateadd(year, -1, thedate
then SaleCost else 0
end)
From (select cast('2015-01-01' as date) as thedate
) params cross join
Details_Orders o
group by CustomerName;

Related

Return 1 row with various sums based on date?

Assume a table of purchase transactions with columns CustId, Amount, DatePosted where Amount is the value of the transaction, and DatePosted is a DATETIME value. Given a specific CustId, how would I write a select such that it returns a single row with the following columns: CustId, total value of transactions in the last 3 days, last 60 days, 1 year, 2 years (5 columns total).
Example table:
CustId
Amount
DatePosted
1234
698.02
2023-01-23Z12:34:56
1234
582.69
2022-12-15Z19:57:23
1234
7775.22
2022-12-02Z02:34:32
1234
18.72
2022-01-23Z12:34:56
1234
2.27
2021-01-23Z12:34:56
Expected output given the sample data above when searching using CustId=1234:
CustId
3-day Total
60-day Total
1 year Total
2 year Total
1234
698.02
9055.93
9074.65
9076.92
You could get all purchase data for the last 2 years, then using SUM with SQL CASE expression to calculate total value for each time-range.
SELECT
CustId,
SUM(CASE WHEN DatePosted >= Last3Day THEN Amount ELSE 0 END) AS [3-day Total],
SUM(CASE WHEN DatePosted >= Last60Day THEN Amount ELSE 0 END) AS [60-day Total],
SUM(CASE WHEN DatePosted >= Last1Year THEN Amount ELSE 0 END) AS [1 year Total],
SUM(CASE WHEN DatePosted >= Last2Year THEN Amount ELSE 0 END) AS [2 year Total]
FROM
<your data table>,
(SELECT
DATEADD(DAY, -3, GETDATE()) AS Last3Day,
DATEADD(DAY, -60, GETDATE()) AS Last60Day,
DATEADD(YEAR, -1, GETDATE()) AS Last1Year,
DATEADD(YEAR, -2, GETDATE()) AS Last2Year) timerange
WHERE DatePosted >= Last2Year
GROUP BY CustId;
Demo: http://sqlfiddle.com/#!18/9eecb/179880
This query assumes 2 year max. If you want to go further back then change the where clause as well. No need to use coalesce or a derived table. SQL server query planner may be smart enough to provide similar performance for all these solutions but this is easier to understand:
SELECT
CustId,
SUM(CASE WHEN DatePosted >= DATEADD(day, -3, GETDATE()) THEN Amount ELSE 0 END) AS [3-day Total],
SUM(CASE WHEN DatePosted >= DATEADD(day, -60, GETDATE()) THEN Amount ELSE 0 END) AS [60-day Total],
SUM(CASE WHEN DatePosted >= DATEADD(year, -1, GETDATE()) THEN Amount ELSE 0 END) AS [1 year Total],
SUM(Amount) AS [2 year Total]
FROM PurchaseTransactions
WHERE CustId = 1234 AND DatePosted >= DATEADD(year, -2, GETDATE())
GROUP BY CustId
This is set up so that you can set #CustID = null and the query will return results for all customers in the set.
EDIT: Updated my query below to give you more flexibility across your desired ranges should you wish to derive additional heuristics. (Counts, averages, etc.)
Also removed coalesce as it's simply not needed here.
DECLARE #CustID BIGINT;
SELECT table1.custID,
SUM([3Day].amount) AS [3DayTotal],
COUNT([3Day].amount) AS [3DayCount]
SUM([60Day].amount) AS [60DayTotal],
SUM([1Year].amount) AS [1YearTotal],
Sum([2Year].amount) AS [2YearTotal],
AVG([2Year].amount) AS [2YearAverage]
FROM table1 LEFT OUTER JOIN
(SELECT custID, Amount FROM table1 WHERE DatePosted > DATEADD(DAY, -3, GETDATE())) AS [3Day] ON table1.CustID = [3Day].CustID LEFT OUTER JOIN
(SELECT custID, Amount FROM table1 WHERE DatePosted > DATEADD(DAY, -60, GETDATE())) AS [60Day] ON table1.CustID = [60Day].CustID LEFT OUTER JOIN
(SELECT custID, Amount FROM table1 WHERE DatePosted > DATEADD(YEAR, -1, GETDATE())) AS [1Year] ON table1.CustID = [1Year].CustID LEFT OUTER JOIN
(SELECT custID, Amount FROM table1 WHERE DatePosted > DATEADD(YEAR, -2, GETDATE()) AS [2Year] ON table1.CustID = [2Year].CustID
WHERE table1.CustID = #CustID
OR #CustID IS NULL
GROUP BY table1.CustID

Need to get number of Items used in last 3 days as well as used items in last year

I have the query where I can fetch last 3 days records perfectly
Select ProductID, Description, Count(productID) AS [Last 3 days item count]
From VIEW_ItemsUsed
Where DateUsed >= Getdate()-3
Group by ProductID
But when I include the condition for fetching the number of items used in last year in the same query, getting invalid data
Select ProductID, Description, Count(productID) AS [Last 3 days item count], Count(ProductID) AS [Last Year Item counts]
From VIEW_ItemsUsed
Where DateUsed >= Getdate()-3
AND DateUsed >= Getdate()-365
Group by ProductID
Please provide me the solution
I think you just want conditional aggregation:
Select ProductID, Description,
sum(case when dateUsed >= getdate() - 3 then 1 else 0 end) as cnt_3days,
sum(case when dateUsed >= getdate() - 365 then 1 else 0 end) as cnt_365days
From VIEW_ItemsUsed
Where DateUsed >= Getdate() - 365
Group by ProductID, Description;

How to handle aggregate function in Case statements when it involves date columns

I'm calculating invoiceDate vs currentDate then sum Value/Amount column grouping by Customer but its returning "invoiceDate is not contained in either an aggregate function or the GROUP BY clause"
select Customer
,case
when datediff(dd,InvoiceDate,getdate()) <=30 then sum(InvoiceBal1)
else 0
end as [Current]
,case
when datediff(dd,InvoiceDate,getdate()) between 31 and 60 then sum(InvoiceBal1)
else 0
end as [30 Days]
from CusInvoice
group by Customer
You want conditional aggregation:
select Customer
sum(case when datediff(day, InvoiceDate, getdate()) <= 30
then InvoiceBal1 else 0
end) as balance_current
sum(case when datediff(day, InvoiceDate, getdate()) between 31 and 60
then InvoiceBal1 else 0
end) as balance_30days
from CusInvoice
group by Customer

Total Count of each

I have a problem with my SQL Server query.
My query must display the total number of each category. Not the total amount of all categories.
SELECT [CATEGORY],
(SELECT COUNT(*)
FROM [Group_New_DB].[dbo].[INCIDENTSM1]
WHERE ([OPEN_TIME] >= #StartDate and [OPEN_TIME] < #EndDate + 1) ) AS OpenedCount,
(SELECT COUNT(*)
FROM [Group_New_DB].[dbo].[INCIDENTSM1]
WHERE ([CLOSE_TIME] >= #StartDate and [CLOSE_TIME] < #EndDate + 1)) AS ClosedCount
FROM [Group_New_DB].[dbo].[INCIDENTSM1]
GROUP BY CATEGORY
ORDER BY CATEGORY
The report consists of a table with 3 columns: Category, Registered, Closed.
1 column is the category name.
2 column is how many categories have been registered.
3 column -> how many columns were closed.
But result
The result that turned out as a result does not look right.
I don't quite understand what is the difference between total number vs total amount as the question doesn't provide any context.
Although, if you are trying to get OpenedCount and ClosedCount as you have named the columns, I suggest you try below:
SELECT
CATEGORY,
SUM(CASE WHEN (OPEN_TIME >= #start_date AND OPEN_TIME < #end_date+1)
THEN 1
ELSE 0
END) AS OPENED_COUNT,
SUM(CASE WHEN (CLOSED_TIME >= #start_date AND CLOSED_TIME < #end_date+1)
THEN 1
ELSE 0
END) AS CLOSED_COUNT
FROM
[Group_New_DB].[dbo].[INCIDENTSM1]
GROUP BY
CATEGORY
ORDER BY
CATEGORY
IMO, This is also a better way as it doesn't include multiple sub-queries.
Correction: changed COUNT to SUM as suggested by TriV - Thanks!
Try this instead -
SELECT [CATEGORY],
COUNT(CASE WHEN [OPEN_TIME] >= #StartDate and [OPEN_TIME] < #EndDate + 1 THEN 1 ELSE NULL END) AS OpenedCount,
COUNT(CASE WHEN [CLOSE_TIME] >= #StartDate and [CLOSE_TIME] < #EndDate + 1 THEN 1 ELSE NULL END) AS ClosedCount
FROM [Group_New_DB].[dbo].[INCIDENTSM1] GROUP BY
CATEGORY ORDER BY CATEGORY

SQL Query: Including Two Sums based on different criteria from the same table

I currently have the following sql query
SELECT [Date], DATENAME(dw,[Date]) AS Day, SUM(Units) AS TotalUnits
FROM tblTimesheetEntries
WHERE UserID = 'PJW'
AND Date >= '2013-01-01'
GROUP BY [Date]
ORDER BY [Date] DESC;
Which returns the Total [Units] for a given user and date.
However I would like to produce two separate Total Units based on a new criteria i.e. whether or not the [Units] where 'Chargeable or Not'. There is a field in tblTimeSheets called Chargeable which is a boolean (true for chargeable, false for not). How do I incorporate this to show two Sums one for each type of Units?
You can use a CASE with the SUM() to calculate the separate totals:
SELECT [Date],
DATENAME(dw,[Date]) AS Day,
sum(case when Chargeable = 1 then Units else 0 end) ChargeableTotal,
sum(case when Chargeable = 0 then Units else 0 end) NotChargeableTotal,
sum(Units) AS TotalUnits
FROM tblTimesheetEntries
WHERE UserID = 'PJW'
AND Date >= '2013-01-01'
GROUP BY [Date]
ORDER BY [Date] DESC;