Grouping by several variables in SAS - sql

I want to sum up sales across agents, orders and the date. The following code runs, however, I just receive a duplicate of the total column instead of the sum. Any advice?
CODE:
(Select DISTINCT DATE, CUSTOMER, ORDERNR,
AREA, AGENT, Total, SUM(Total) AS TOTALSUM From data01 WHERE REPORT_DT between '2018-02-24' and '2018-02-25' GROUP BY DATE, CUSTOMER, ORDERNR,
AREA, AGENT, Total, ORDER BY AGENT)

Just a suggestion for clean your code that contain some error
You don't need distinct whe use GROUP BY and you have a wrong comma after the word Total in group by
(Select
DATE
, CUSTOMER
, ORDERNR
, AREA
, AGENT
, Total
, SUM(Total) AS TOTALSUM
From data01
WHERE REPORT_DT between '2018-02-24' and '2018-02-25'
GROUP BY DATE
, CUSTOMER
, ORDERNR
, AREA
, AGENT
, Total
ORDER BY AGENT)

Remove Total from the GROUP BY:
Select DATE, CUSTOMER, ORDERNR, AREA, AGENT, SUM(Total) AS TOTALSUM
From data01
where REPORT_DT between '2018-02-24' and '2018-02-25'
group by DATE, CUSTOMER, ORDERNR, AREA, AGENT;

Related

Can't use order when grouped by in BigQuery

I want to group by FECHA_COMPRA and then order by the same field. But when I do this, I get an error message:
SELECT list expression references column FECHA_COMPRA which is neither grouped nor aggregated at [28:13]
This are the querys I'm using:
Select DATE(FECHA_COMPRA) as Date,TYPE,SUM(AMOUNT) AS Total, SUM(Quantity) as Qty FROM Test
GROUP BY DATE(FECHA_COMPRA)
Order by date(FECHA_COMPRA)
This is also not working:
Select DATE(FECHA_COMPRA) as Date,TYPE,SUM(AMOUNT) AS Total, SUM(Quantity) as Qty FROM Test
GROUP BY DATE(FECHA_COMPRA)
Order by FECHA_COMPRA
What is wrong?
Thanks!
Use below instead
select
date(fecha_compra) as date,
type,
sum(amount) as total,
sum(quantity) as qty
from test
group by date, type
order by date

How to add a new column that summarize rows

I have two issues :
I used 'Rollup' function to add Totals per Month and Year and I would like to change 'NULL' into grand_total as in the attached screenshot
I dont know how to add a new column that will summarize values starting from the second row
Please see attached screenshot of the results I need to receive and an example for a code from my side with a screenshot of the source output : [1]: https://i.stack.imgur.com/6B70o.png
[1]: https://i.stack.imgur.com/E2x8K.png
Select Year(Modifieddate) AS Year,
MONTH(modifieddate) as Month,
Sum(linetotal) as Sum_price
from Sales.SalesOrderDetail
Group by rollup( Year(Modifieddate),MONTH(modifieddate))
Thanks in advance,
I think this will work:
Select Year(Modifieddate) AS Year,
coalesce(convert(varchar(255), month(modifieddate)), 'Grand Total') as Month,
Sum(linetotal) as Sum_price,
sum(sum(linetotal)) over (partition by Year(Modifieddate)
order by coalesce(month(modifieddate), 100)
) as ytd_sum_price
from Sales.SalesOrderDetail
Group by rollup( Year(Modifieddate), month(modifieddate))
The coalesce() in the order by is to put the summary row last for the cumulative sum.
Like this:
Select Year(Modifieddate) AS Year, MONTH(modifieddate) as Month, Sum(linetotal) as Sum_price
from Sales.SalesOrderDetail
Group by rollup( Year(Modifieddate),MONTH(modifieddate))
UNION
Select Year(Modifieddate) AS Year, 'grand_total' as Month, Sum(linetotal) as Sum_price
from Sales.SalesOrderDetail
Group by Year(Modifieddate)
-- SQL SERVER
SELECT t.OrderYear
, CASE WHEN t.OrderMonth IS NULL THEN 'Grand Total' ELSE CAST(t.OrderMonth AS VARCHAR(20)) END b
, t.MonthlySales
, MAX(t.cum_total) cum_total
FROM (SELECT
YEAR(OrderDate) AS OrderYear,
MONTH(OrderDate) AS OrderMonth,
SUM(SubTotal) AS MonthlySales,
SUM(SUM(SubTotal)) OVER (ORDER BY YEAR(OrderDate), MONTH(OrderDate) ROWS UNBOUNDED PRECEDING) cum_total
FROM Sales.SalesOrderHeader
GROUP BY GROUPING SETS ((YEAR(OrderDate), MONTH(OrderDate)))) t
GROUP BY GROUPING SETS ((t.OrderYear
, t.OrderMonth
, t.MonthlySales), t.OrderYear);
Please check this url https://dbfiddle.uk/?rdbms=sqlserver_2019&sample=adventureworks&fiddle=e6cd2ba8114bd1d86b8c61b1453cafcf
To build one #GordonLinoff's answer, you are really supposed to use the GROUPING() function to check whether you are dealing with the grouping column. This behaves better in the face of nullable columns.
Select case when grouping(Year(Modifieddate)) = 0
then Year(Modifieddate)
else 'Grand Total' end AS Year,
case when grouping(month(modifieddate)) = 0
then convert(varchar(255), month(modifieddate))
else 'Grand Total' end as Month,
Sum(linetotal) as Sum_price,
sum(sum(linetotal)) over (
partition by
grouping(Year(Modifieddate)),
grouping(month(modifieddate)),
Year(Modifieddate)
order by month(modifieddate)
) as ytd_sum_price
from Sales.SalesOrderDetail
Group by rollup( Year(Modifieddate), month(modifieddate));

Summing a column over a date range in a CTE?

I'm trying to sum a certain column over a certain date range. The kicker is that I want this to be a CTE, because I'll have to use it multiple times as part of a larger query. Since it's a CTE, it has to have the date column as well as the sum and ID columns, meaning I have to group by date AND ID. That will cause my results to be grouped by ID and date, giving me not a single sum over the date range, but a bunch of sums, one for each day.
To make it simple, say we have:
create table orders (
id int primary key,
itemID int foreign key references items.id,
datePlaced datetime,
salesRep int foreign key references salesReps.id,
price int,
amountShipped int);
Now, we want to get the total money a given sales rep made during a fiscal year, broken down by item. That is, ignoring the fiscal year bit:
select itemName, sum(price) as totalSales, sum(totalShipped) as totalShipped
from orders
join items on items.id = orders.itemID
where orders.salesRep = '1234'
group by itemName
Simple enough. But when you add anything else, even the price, the query spits out way more rows than you wanted.
select itemName, price, sum(price) as totalSales, sum(totalShipped) as totalShipped
from orders
join items on items.id = orders.itemID
where orders.salesRep = '1234'
group by itemName, price
Now, each group is (name, price) instead of just (name). This is kind of sudocode, but in my database, just this change causes my result set to jump from 13 to 32 rows. Add to that the date range, and you really have a problem:
select itemName, price, sum(price) as totalSales, sum(totalShipped) as totalShipped
from orders
join items on items.id = orders.itemID
where orders.salesRep = '1234'
and orderDate between 150101 and 151231
group by itemName, price
This is identical to the last example. The trouble is making it a CTE:
with totals as (
select itemName, price, sum(price) as totalSales, sum(totalShipped) as totalShipped, orderDate as startDate, orderDate as endDate
from orders
join items on items.id = orders.itemID
where orders.salesRep = '1234'
and orderDate between startDate and endDate
group by itemName, price, startDate, endDate
)
select totals_2015.itemName as itemName_2015, totals_2015.price as price_2015, ...
totals_2016.itemName as itemName_2016, ...
from (
select * from totals
where startDate = 150101 and endDate = 151231
) totals_2015
join (
select *
from totals
where startDate = 160101 and endDate = 160412
) totals_2016
on totals_2015.itemName = totals_2016.itemName
Now the grouping in the CTE is way off, more than adding the price made it. I've thought about breaking the price query into its own subquery inside the CTE, but I can't escape needing to group by the dates in order to get the date range. Can anyone see a way around this? I hope I've made things clear enough. This is running against an IBM iSeries machine. Thank you!
Depending on what you are looking for, this might be a better approach:
select 'by sales rep' breakdown
, salesRep
, '' year
, sum(price * amountShipped) amount
from etc
group by salesRep
union
select 'by sales rep and year' breakdown
, salesRep
, convert(char(4),orderDate, 120) year
, sum(price * amountShipped) amount
from etc
group by salesRep, convert(char(4),orderDate, 120)
etc
When possible group by the id columns or foreign keys because the columns are indexed already you'll get faster results. This applies to any database.
with cte as (
select id,rep, sum(sales) sls, count(distinct itemid) did, count(*) cnt from sommewhere
where date between x and y
group by id,rep
) select * from cte order by rep
or more fancy
with cte as (
select id,rep, sum(sales) sls, count(distinct itemid) did, count(*) cnt from sommewhere
where date between x and y
group by id,rep
) select * from cte join reps on cte.rep = reps.rep order by sls desc
I eventually found a solution, and it doesn't need a CTE at all. I wanted the CTE to avoid code duplication, but this works almost as well. Here's a thread explaining summing conditionally that does exactly what I was looking for.

How to sort by Total Sum calculated field in a Tablix

I have a Report in Microsoft Visual Studio 2010 that has a tablix. I have a list of Customers Sales grouped by Month. I would like to add a grand total of all the Months for each customer. I would then like to sort by descending amount of the grand total. I have added the grand total, but I can't figure out how to sort on it. Any suggestions?
Here is the initial dataset query:
SELECT
Customer, CustomerName, FiscalMonthNum, FiscalYear, SalesDlr
FROM
CustomerSalesDollars
WHERE
FiscalYear IN ('2013')
ORDER BY
SalesDlr DESC
with CSD as (
select Customer, CustomerName, FiscalMonthNum, FiscalYear, SalesDlr
from CustomerSalesDollars
WHERE FiscalYear in ('2013')
), YearlyTotals as (
select FiscalYear, Customer, CustomerName, SUM(SalesDlr) as YearlyTotal
from CSD
group by FiscalYear, Customer, CustomerName
)
select * from YearlyTotals
order by YearlyTotal desc
If you still want all the monthly breakdowns:
with CSD as (
select Customer, CustomerName, FiscalMonthNum, FiscalYear, SalesDlr
from CustomerSalesDollars
WHERE FiscalYear in ('2013')
), YearlyTotals as (
select FiscalYear, Customer, CustomerName, SUM(SalesDlr) as YearlyTotal
from CSD
group by FiscalYear, Customer, CustomerName
)
select CSD.*, YT.YearlyTotal from YearlyTotals YT
join CSD on CSD.FiscalYear = YT.FiscalYear
and CSD.Customer = YT.Customer
and CSD.CustomerName = YT.CustomerName
order by YearlyTotal desc, CSD.SalesDlr desc

SQL subquery to calculate frequency over average frequency

I want to create a chart that will represent the performance of some stores.
The x axis will represent the total revenue of the store over the average revenue of all the stores.
And the y axis will represent the average frequency the customers of a specific store visit this store over the average frequency all the customers visit all the stores.
This is what I have tried :
select
distinct [Order].shop_id
, SUM(total) /((select AVG(o.shopTotal)
from
(
select
distinct shop_id , SUM(total) as shopTotal
from [Order]
group by shop_id
)o)*0.1) as revPerAvgRev
,COUNT(distinct orderno) /((select AVG(orders)
from
(
select
distinct shop_id , room, COUNT(distinct orderno) as orders
from [Order]
group by shop_id , room
)o)*0.1) as freqPerAvgFreq
from [Order]
group by [order].shop_id
order by revPerAvgRev desc
select distinct shop_id ,room , count(distinct orderno)
from [Order]
group by shop_id , room
I believe the average frequency that the customers visit the stores is ok.
But I cannot manage to calculate correclty the average frequency each customer visit the store.
Note: Each customer only visits one store.
It is a little difficult to follow exactly what you want. You ask for frequencies but the code sample is showing revenue. You can get the proportion of revenue by using a window function to calculate the total:
select shop_id, shopTotal,
cast(shopTotal as float)/ sum(shopTotal) over () as Revenue,ProportionOfTotal,
numvisits,
cast(numvisits as float) / sum(numvisits) over () as VisitsProportionOfTotal
from (select shop_id , SUM(total) as shopTotal, count(*) as numvisits
from [Order]
group by shop_id
) s