Transact-SQL query subtotal column - sql

When my sql query returns the results it looks like this:
Driver Amount
A $120.00
A -$5.00
A $10.00
B $90.00
But now I've been requested to add a column to the query results that will present the total for each driver. So it should now look like this:
Driver Amount Subtotal
A $120.00 $125.00
A -$5.00 $125.00
A $10.00 $125.00
B $90.00 $90.00
Possible?

Use window functions.
with cte as (
<your query here>
)
select cte.*,
sum(amount) over (partition by driver) as subtotal
from cte;
You can probably incorporate this logic directly into the query that returns the first results as well.

Sorry that I can't provide you with the full query, but the following link may help accomplish what you need with GROUP BY and ROLLUP, if you're using MS SQL.
https://technet.microsoft.com/en-us/library/bb522495(v=sql.105).aspx
one other way of doing this would be to use CTE (Common Table Expression)
With cteName as (
Select DriverId,
Sum(DriverAmount) As TotalDriverAmount
FROM YourTable
GROUP BY DriverId
),
Select YourTable.DriverId, DriverAmount, cteName.TotalDriverAmount
FROM YourTable LEFT JOIN cteName ON(cteName.DriverId = YourTable.DriverId)

SELECT T.DRIVER, T.AMOUNT, S.TOT [SUBTOTAL] FROM YOURTABLE T JOIN
(SELECT DRIVER, SUM(AMOUNT) TOT FROM YOURTABLE GROUP BY DRIVER ) S
ON T.DRIVER = S.DRIVER
This should work on just about any MS-SQL version.

From
https://www.sqlservercentral.com/Forums/Topic1541134-3412-1.aspx
This is really easy thanks to some (Windowing) functionality born in 2005.
SELECT OrderNo
,Something
,Amount
,SubTotal = SUM(Amount) OVER (PARTITION BY OrderNo)
FROM #TestTable
ORDER BY OrderNo, Something

Create a function that get driver Id, query driver data and return total, call that function in query
Select DriverId, Amount, func(driverId) as TotalAmount
FROM Table
function func(ID){
return(Select sum(amount) from table where driverid=ID);
}

Related

How to select all columns with sum function

Assuming there is a table with 100 columns, how can I select all columns with a sum without having to type out all the columns?
For example something like this:
select *, sum(price) as sales
from table
group by *
order by date
try this
select table.* , t.sales from table
inner join (select id, sum(price) as sales from table group by id ) t
on table.id=t.id
order by date
But in general it is not recommended to use an stare in a select statement,
for example dont use * in table-valued function

SQL window function over partition by syntax error

I have a test table with two columns brand and store
brand
store
A
a
A
b
B
a
I'm trying to use the window function to get the output like this
brand
store
num_stores
A
a
2
A
b
2
B
a
1
Here's what I've been trying on both presto sql and sqlite but keep getting "(" syntax error.
select brand, store,
count(store) OVER (PARTITION BY brand) as num_stores
from table
Struggling to find why I got this error and how to fix. Appreciate your help :))
It could be that your particular database does not support analytic functions. In that case, you could, as a workaround, try the following:
SELECT t1.brand, t1.store, t2.cnt AS num_stores
FROM yourTable t1
INNER JOIN
(
SELECT brand, COUNT(store) AS cnt
FROM yourTable
GROUP BY brand
) t2
ON t2.brand = t1.brand;
You can try with the below query:
select brand, store, count(*) OVER (PARTITION BY brand, store) as
num_stores from table;
You are missing () brackets for alias covering. You can check my query in db-fiddle
SELECT
Brand,
Store,
(COUNT(Store) OVER (PARTITION BY Brand)) as Num_Stores
FROM your_table

SQL Total Distinct Count on Group By Query

Trying to get an overall distinct count of the employees for a range of records which has a group by on it.
I've tried using the "over()" clause but couldn't get that to work. Best to explain using an example so please see my script below and wanted result below.
EDIT:
I should mention I'm hoping for a solution that does not use a sub-query based on my "sales_detail" table below because in my real example, the "sales_detail" table is a very complex sub-query.
Here's the result I want. Column "wanted_result" should be 9:
Sample script:
CREATE TEMPORARY TABLE [sales_detail] (
[employee] varchar(100),[customer] varchar(100),[startdate] varchar(100),[enddate] varchar(100),[saleday] int,[timeframe] varchar(100),[saleqty] numeric(18,4)
);
INSERT INTO [sales_detail]
([employee],[customer],[startdate],[enddate],[saleday],[timeframe],[saleqty])
VALUES
('Wendy','Chris','8/1/2019','8/12/2019','5','Afternoon','1'),
('Wendy','Chris','8/1/2019','8/12/2019','5','Morning','5'),
('Wendy','Chris','8/1/2019','8/12/2019','6','Morning','6'),
('Dexter','Chris','8/1/2019','8/12/2019','2','Mid','2.5'),
('Jennifer','Chris','8/1/2019','8/12/2019','4','Morning','2.75'),
('Lila','Chris','8/1/2019','8/12/2019','2','Morning','3.75'),
('Rita','Chris','8/1/2019','8/12/2019','2','Mid','1'),
('Tony','Chris','8/1/2019','8/12/2019','4','Mid','2'),
('Tony','Chris','8/1/2019','8/12/2019','1','Morning','6'),
('Mike','Chris','8/1/2019','8/12/2019','4','Mid','1.5'),
('Logan','Chris','8/1/2019','8/12/2019','3','Morning','6.25'),
('Blake','Chris','8/1/2019','8/12/2019','4','Afternoon','0.5')
;
SELECT
[timeframe],
SUM([saleqty]) AS [total_qty],
COUNT(DISTINCT [s].[employee]) AS [employee_count1],
SUM(COUNT(DISTINCT [s].[employee])) OVER() AS [employee_count2],
9 AS [wanted_result]
FROM (
SELECT
[employee],[customer],[startdate],[enddate],[saleday],[timeframe],[saleqty]
FROM
[sales_detail]
) AS [s]
GROUP BY
[timeframe]
;
If I understand correctly, you are simply looking for a COUNT(DISTINCT) for all employees in the table? I believe this query will return the results you are looking for:
SELECT
[timeframe],
SUM([saleqty]) AS [total_qty],
COUNT(DISTINCT [s].[employee]) AS [employee_count1],
(SELECT COUNT(DISTINCT [employee]) FROM [sales_detail]) AS [employee_count2],
9 AS [wanted_result]
FROM #sales_detail [s]
GROUP BY
[timeframe]
You can try this below option-
SELECT
[timeframe],
SUM([saleqty]) AS [total_qty],
COUNT(DISTINCT [s].[employee]) AS [employee_count1],
SUM(COUNT(DISTINCT [s].[employee])) OVER() AS [employee_count2],
[wanted_result]
-- select count form sub query
FROM (
SELECT
[employee],[customer],[startdate],[enddate],[saleday],[timeframe],[saleqty],
(select COUNT(DISTINCT [employee]) from [sales_detail]) AS [wanted_result]
--caculate the count with first sub query
FROM [sales_detail]
) AS [s]
GROUP BY
[timeframe],[wanted_result]
Use a trick where you only count each person on the first day they are seen:
select timeframe, sum(saleqty) as total_qty),
count(distinct employee) as employee_count1,
sum( (seqnum = 1)::int ) as employee_count2
9 as wanted_result
from (select sd.*,
row_number() over (partition by employee order by startdate) as seqnum
from sales_detail sd
) sd
group by timeframe;
Note: From the perspective of performance, your complex subquery is only evaluated once.

SQL query scenario.

Suppose I have the following table:
My goal is to display a select resultset that looks like this:
The tricky part here is to display the AverageCostPerType column for every single book.
I know how to get the AverageCostPerType, it's simply the following:
SELECT avg(bookcost) as AverageCostPerType FROM BOOK GROUPBY BookType;
This will display 3 rows since I have 3 distinct types. How can I display an averagecostpertype for each book ?
I'll appreciate your help.
you need use analytic functions
AVG per BookType
select b.*, avg(bookcost) over (PARTITION BY BookType)
from book b
AVG for all books
select b.*, avg(bookcost) over ()
from book b
You can use aggregate functions with an analytic partition window to get average cost by booktype.
This allows you to perform the query without joining the table to itself, or using nested select statements.
Oracle Aggregate Functions
select Book_num,
BookType,
avg(BookCost) over(partition by BookType) as AverageCostPerType,
BookCost,
BookCost - avg(BookCost) over(partition by BookType) as Difference
from YourBookTable
You can calculate the average per booktype in a derived table and join it to the original table to get the result.
select book_num, t.booktype, x.avgcost, bookcost, x.avgcost-bookcost
from tablename t join
(select booktype, avg(bookcost) as avgcost from tablename group by booktype) x
on t.booktype = x.booktype
select b.*,
b2.AverageCostPerType,
b2.AverageCostPerType - b.BookCost as difference
from book b
join
(
SELECT BookType, avg(bookcost) as AverageCostPerType
FROM BOOK
GROUP BY BookType
) b2 on b.BookType = b2.BookType

SQL Server 2012 Group only by one column

I need to group only by one column
SQL Server 2012 query:
SELECT OrderID,Status,DateEdited
FROM orders
WHERE Status='Pending'
GROUP BY OrderID,Status,DateEdited
and the result is:
As you can see there are duplicate OrderId column values.
Works but it groups by OrderId,Status,DateEdit but what I need is that the OrderId would be unique in the results can I have something like:
SELECT OrderID,Status,DateEdited
FROM orders
WHERE Status='Pending'
GROUP BY OrderID
You have to use an aggregate function for status and DateEdited, to get distinct valeus for each grouped ORDERID. You can also use the ranking functions to do so like this:
WITH CTE
AS
(
SELECT
OrderID,
Status,
DateEdited,
ROW_NUMBER() OVER(PARTITION BY OrderID ORDER BY DateEdited DESC) rownum
FROM orders
WHERE Status='Pending'
)
SELECT
OrderID,
Status,
DateEdited
FROM CTE
WHERE rownum = 1;
This will give you distinct ORDERIDs. But which status and DateEdited to return for each grouped ORDERID?
Then you can do like this,
SELECT OrderID,'Pending' as Status,max(DateEdited)
FROM orders
WHERE Status='Pending'
GROUP BY OrderID
If you dont want to loose any record then you can go for
GROUP_CONCAT()
SELECT OrderID,'Pending' as Status,GROUP_CONCAT(DateEdited)
FROM orders
WHERE Status='Pending'
GROUP BY OrderID
Note: Am not sure whether you GROUP_CONCAT in sqlserver Incase it's not there
go for a function like that. :)