Add a Total Row after each Unique CustomerName - sql

I am trying to add a 'Total' row after each Unique CustomerName. I have tried ROLLUP and it does not seem to work properly because of the amount of fields i am trying to group by. An example of what i am looking for would pseudo be
(
FlavorName('Total'), 2016Sales (Sum of total sales), 2017Sales (Sum of total sales), 2016TotalPounds (Sum of total pounds), 2017TotalPounds (Sum of total pounds))
Please find my current code below.
WITH cte AS (SELECT CustName AS CustomerName, ItemKey AS CICode, Description AS FlavorName, CASE WHEN InvoiceDate BETWEEN '2016-01-01' AND
'2016-12-31' THEN SUM(LineNet) ELSE 0 END AS [2016TotalSales], CASE WHEN InvoiceDate BETWEEN '2017-01-01' AND getdate() THEN SUM(LineNet)
ELSE 0 END AS [2017TotalSales], CASE WHEN InvoiceDate BETWEEN '2016-01-01' AND '2016-12-31' THEN ROUND(SUM(QtyOrd), 2)
ELSE 0 END AS [2016TotalPounds], CASE WHEN InvoiceDate BETWEEN '2017-01-01' AND getdate() THEN ROUND(SUM(QtyOrd), 2)
ELSE 0 END AS [2017TotalPounds], BasePrice, SUBSTRING(CAST(InvoiceDate AS nvarchar(50)), 8, 5) AS year, UOM
FROM dbo.ABC
GROUP BY CustName, ItemKey, Description, BasePrice, InvoiceDate, UOM)
SELECT TOP (100) PERCENT CustomerName, CASE WHEN CICode IS NULL THEN 'ALL' ELSE CICode END AS CICode, CASE WHEN BasePrice IS NULL
THEN 'TOTALS' ELSE FlavorName END AS FlavorName, SUM([2016TotalSales]) AS [2016Sales], SUM([2017TotalSales]) AS [2017Sales], SUM([2016TotalPounds])
AS [2016TotalPounds], ROUND(SUM([2017TotalPounds]), 2) AS [2017TotalPounds], UOM, ISNULL(ROUND((SUM([2017TotalPounds]) - SUM([2016TotalPounds]))
/ NULLIF (SUM([2016TotalPounds]), 0) * 100, 2), 100) AS [%Change], BasePrice
FROM cte AS cte_1
GROUP BY CustomerName, CICode, FlavorName, BasePrice, UOM
HAVING (SUM([2016TotalSales]) + SUM([2017TotalSales]) > 0)

Try GROUPING SETS:
GROUP BY GROUPING SETS ( (CustomerName, CICode, FlavorName, BasePrice, UOM), (CustomerName) )
You may have to play with ORDER BY to get the results in the particular order that you want.

Related

SQL Server Query retrieves incorrect value

Below is transaction item table.
Now I wanted to retrieve total amount of the transaction, total amount with discount, total discount and Sales Tax for which I wrote the below query:
select t1.av_transaction_id,
round(SUM((t1.gross_line_amount - t1.pos_discount_amount)), 2) AS total_amount_with_discount,
round(SUM((t1.gross_line_amount)), 2) AS total_amount,
round(SUM((t1.pos_discount_amount)), 2) AS total_discount,
round(SUM((t2.gross_line_amount)), 2) AS total_sales_tax
from transaction_detail as t1
inner join transaction_detail as t2 on t1.av_transaction_id=t2.av_transaction_id
and t1.transaction_date=t2.transaction_date
where (t1.sku_id is not null or t1.line_action_display_descr='sold')
and t2.line_object_description='S6 Sales Tax'
and t1.av_transaction_id='581280193'
group by t1.av_transaction_id
But I get the following output:
av_transaction_id:581280193 || total_amount_with_discount:5.01 || total_amount:6.67 || total_discount:1.66 || total_Sales_tax:0.66
As you may see in the screenshot the Sales Tax should be 0.22 but somehow the query returns 0.66.
Can someone pleas help me in optimizing this query and let me know why does it return an incorrect value ?
There are three records for this transaction where the sku_id is not null or the display description is 'sold'. All three of those will match with the Sales Tax record for the join... and then you take the SUM(). So .22 + .22 + .22 = .66
To fix this, I'd use conditional aggregation rather than a self-join:
select t1.av_transaction_id,
round(SUM(CASE WHEN t1.sku_id is not null or t1.line_action_display_descr='sold' THEN t1.gross_line_amount - t1.pos_discount_amount ELSE 0 END)), 2) AS total_amount_with_discount,
round(SUM(CASE WHEN t1.sku_id is not null or t1.line_action_display_descr='sold' THEN t1.gross_line_amount ELSE 0 END), 2) AS total_amount,
round(SUM(CASE WHEN t1.sku_id is not null or t1.line_action_display_descr='sold' THEN t1.pos_discount_amount ELSE 0 END), 2) AS total_discount,
round(SUM(CASE WHEN t1.line_object_description='S6 Sales Tax' THEN t1.gross_line_amount ELSE 0 END), 2) AS total_sales_tax
from transaction_detail as t1
where t1.av_transaction_id='581280193'
group by t1.av_transaction_id
Though this repeats the same condition, so you might be able to wrap that up further to only resolve the condition once.
This worked for me, thanks to previous respondents:
select t1.av_transaction_id,
round(SUM((t1.gross_line_amount - t1.pos_discount_amount)), 2) AS total_amount_with_discount,
round(SUM((t1.gross_line_amount)), 2) AS total_amount,
round(SUM((t1.pos_discount_amount)), 2) AS total_discount,
round(SUM((t2.gross_line_amount))/count(t1.gross_line_amount), 2) AS total_sales_tax
from transaction_detail as t1 inner join
transaction_detail as t2 on t1.av_transaction_id=t2.av_transaction_id
and t1.transaction_date=t2.transaction_date
where (t1.sku_id is not null or t1.line_action_display_descr='sold')
and t2.line_object_description='S6 Sales Tax'
and t1.av_transaction_id='581280193'
group by t1.av_transaction_id
I think that all you need to do is to not sum the sales tax, so your query would look like this:
select t1.av_transaction_id,
round(SUM((t1.gross_line_amount - t1.pos_discount_amount)), 2) AS total_amount_with_discount,
round(SUM((t1.gross_line_amount)), 2) AS total_amount,
round(SUM((t1.pos_discount_amount)), 2) AS total_discount,
round(t2.gross_line_amount, 2) AS total_sales_tax
from transaction_detail as t1
inner join transaction_detail as t2 on t1.av_transaction_id=t2.av_transaction_id
and t1.transaction_date=t2.transaction_date
where (t1.sku_id is not null or t1.line_action_display_descr='sold')
and t2.line_object_description='S6 Sales Tax'
and t1.av_transaction_id='581280193'
group by t1.av_transaction_id
I mocked up your table with this script:
CREATE TABLE SO_TEST
(
intTransID INT
, objDesc VARCHAR(MAX)
, displayDesc VARCHAR(MAX)
, lintAmt FLOAT
, discAmount FLOAT
)
INSERT INTO SO_TEST (intTransID, objDesc, displayDesc, lintAmt, discAmount)
VALUES
(1,'emp merch','sold',2.29,.57)
, (1,'emp merch','sold',1.89,.47)
, (1,'emp merch tax','sold',2.49,.62)
, (1,'sales tax','charged',.22,0.0)
, (1,'blah','blah',1.0,2.0)
, (2,'emp merch','sold',3.29,1.57)
, (2,'emp merch','sold',2.89,1.47)
, (2,'emp merch tax','sold',3.49,1.62)
, (2,'sales tax','charged',1.22,0.0)
, (2,'blah','blah',1.0,2.0)
And came up with this query that displays what I believe you want to have it display:
SELECT t1.intTransID
, ROUND(SUM(t1.lintAmt - t1.discAmount),2) tot_amt_disc
, ROUND(SUM(t1.lintAmt), 2) tot_amt
, ROUND(SUM(t1.discAmount),2) disc_amt
, ROUND(t2.lintAmt,2) sales_tax
FROM SO_TEST t1
JOIN SO_TEST t2 ON 1=1
AND t1.intTransID = t2.intTransID
WHERE t1.displayDesc IN ('sold','charged')
AND t1.objDesc <> 'sales tax'
AND t2.objDesc = 'sales tax'
GROUP BY t1.intTransID, t2.lintAmt
The results of the query are as follows:
This works for multiple transactions as asked.

Count of record, per day, by user comparative

Looking to see if there is a way to compare the number of orders entered a day and by either a specific user (EDI) or anyone else.
I can return results for per day (but only the days where a value exists) but can't figure out a way to combine all three together (Total - by EDI - by everyone else).
Any assistance greatly appreciated.
select Date, count(Order_ID)
from orders
WHERE Date >=dateadd(day,datediff(day,0,GetDate())- 7,0) and [user] = 'EDI'
and customer = '9686'
GROUP BY Date, [user];
select Date, count(Order_ID)
from orders
WHERE Date >=dateadd(day,datediff(day,0,GetDate())- 7,0) and [user] <> 'EDI'
and customer = '9686'
GROUP BY Date, [user];
select Date, count(Order_ID)
from orders
WHERE Date >=dateadd(day,datediff(day,0,GetDate())- 7,0)
and customer = '9686'
GROUP BY Date, [user];
Use conditional aggregation:
select Date, sum(case when [user] = 'EDI' then 1 else 0 end) as cnt_edi,
sum(case when [user] <> 'EDI' then 1 else 0 end) as cnt_non_edi,
count(*) as total
from orders
where Date >= dateadd(day, datediff(day, 0, GetDate()) - 7, 0) and customer = '9686'
group by Date;

SQL Rollup to Sum Totals of a Grouped Table

I have a table that is grouped by 'Group Type'. What I need is for the last row to display the sum of the values in the above rows in the Total row.
Below is the code currently but I am not sure how to sum multiple fields at once.
Actual
Expected Result
Do I need to add another CASE statement to
select
CASE when GROUP_TYPE is null then 'Total' ELSE GROUP_TYPE END as 'Group Type',
Sum_Amount, TotalER, [Discount Report]
from
(select GROUP_TYPE, sum(cast(AMOUNT as float)) as Sum_Amount FROM [dbo].[a]
where cast(ACTIVITY_DATE as date) between #startdate and #enddate
group by GROUP_TYPE with rollup) a
left join
(select [Charge Group] , sum(cast([Earned Revenue] as float)) as
TotalER, sum(cast(Discount as float)) as 'Discount Report'
from [dbo].[er] group by [Charge Group]) er
on
a.GROUP_TYPE = er.[Charge Group]
select sum(cast([er] as float)) from [dbo].[er]
I would do a union all before the aggregation. This makes it easier to specify the multiple aggregation sets:
select coalesce(group_type, 'Total') as group_type, -- the easy way
sum(amount) as sum_amount, sum(er) as totaler, sum(discount) as discount
from ((select group_type, cast(amount as float) as Amount, 0 as ER, 0 as discount
from [dbo].a
where cast(ACTIVITY_DATE as date) between #startdate and #enddate
) union all
(select [Charge Group], 0, cast([Earned Revenue] as float) as er, cast(Discount as float)
from [dbo].er
where cast(ACTIVITY_DATE as date) between #startdate and #enddate
)
) aer
group by grouping sets ( (group_type), () );

SQL QUERY COUNT THEN ADD

I want to write a query to return all records from a table ,
If a specific column value is under 100 , then add +5 to the Value
Its sum value by each order u will need. According to your original question orderamount <100 then add 5
WITH cte
AS (
SELECT OrderID
,OrderDate
,Customer
,ProductAmount
,sum(orderamount) orderamount
FROM mytable
GROUP BY OrderID
,OrderDate
,Customer
,ProductAmount
)
SELECT OrderID
,OrderDate
,Customer
,ProductAmount
,CASE
WHEN orderamount < 100
THEN orderamount + 5
ELSE orderamount
END Orderamount
FROM cte

How can I add cumulative sum column?

I use SqlExpress
Following is the query using which I get the attached result.
SELECT ReceiptId, Date, Amount, Fine, [Transaction]
FROM (
SELECT ReceiptId, Date, Amount, 'DR' AS [Transaction]
FROM ReceiptCRDR
WHERE (Amount > 0)
UNION ALL
SELECT ReceiptId, Date, Amount, 'CR' AS [Transaction]
FROM ReceiptCR
WHERE (Amount > 0)
UNION ALL
SELECT strInvoiceNo AS ReceiptId, CONVERT(datetime, dtInvoiceDt, 103) AS Date, floatTotal AS Amount, 'DR' AS [Transaction]
FROM tblSellDetails
) AS t
ORDER BY Date
Result
want a new column which would show balance amount.
For example. 1 Row should show -2500, 2nd should -3900, 3rd should -700 and so on.
basically, it requires previous row' Account column's data and carry out calculation based on transaction type.
Sample Result
Well, that looks like SQL-Server , if you are using 2012+ , then use SUM() OVER() :
SELECT t.*,
SUM(CASE WHEN t.transactionType = 'DR'
THEN t.amount*-1
ELSE t.amount END)
OVER(PARTITION BY t.date ORDER BY t.receiptId,t.TransactionType DESC) as Cumulative_Col
FROM (YourQuery Here) t
This will SUM the value when its CR and the value*-1 when its DR
Right now I grouped by date, meaning each day will recalculate this column, if you want it for all time, replace the OVER() with this:
OVER(ORDER BY t.date,t.receiptId,t.TransactionType DESC) as Cumulative_Col
Also, I didn't understand why in the same date, for the same ReceiptId DR is calculated before CR , I've add it to the order by but if thats not what you want then explain the logic better.