Here is My query :
SELECT Name,
Quantity,
Price,
(Quantity*Price)[Total Price]
FROM Menu,
Items_per_Table,
[735294]
WHERE Menu.Item_id = Items_per_Table.Item_id
AND [735294].OrderNo = Items_per_Table.OrderNo
AND Bill_Generated = 'True'
It returns :
Name Quantity Price Total Price
Aerated Drinks 1 30.00 30.00
Fresh Lime Soda/Water 3 60.00 180.00
Here I want the sum of total prices like this : 30+180 = 210 in another column.
How can I perform that ?
It Should Return :
Name Quantity Price Total Price All Over Price
Aerated Drinks 1 30.00 30.00 30
Fresh Lime Soda/Water 3 60.00 180.00 210
For SQL Server 2012, this should do what you need;
SELECT Name,
Quantity,
Price,
(Quantity*Price) [Total Price],
SUM(Quantity*Price) OVER (ORDER BY menu.item_id) [All Over Price]
FROM Menu,
Items_per_Table,
[735294]
WHERE Menu.Item_id = Items_per_Table.Item_id
AND [735294].OrderNo = Items_per_Table.OrderNo
AND Bill_Generated = 'True'
ORDER BY menu.item_id
SUM(...) OVER (ORDER BY...) does the running sum in the order you give it. Since you have no order in your question, I arbitrarily chose menu.item_id to order by.
EDIT: Forgot to add the SQLfiddle to test with.
Try using Common Table Expressions,(If you are using SQL < SQl 2012)
;with cteabc
as (
SELECT Name,
Quantity,
Price,
(Quantity*Price)[Total Price]
FROM Menu,
Items_per_Table,
[735294]
WHERE Menu.Item_id = Items_per_Table.Item_id
AND [735294].OrderNo = Items_per_Table.OrderNo
AND Bill_Generated = 'True'
)
select
t1.Name,
t1.Quantity,
t1.Price,
rt.runningTotal
from cteabc t1
cross apply (select sum([Total Price]) as runningTotal
from cteabc t2
where t2.rn<= t1.rn
) as rt
order by t1.Name
SQL Fiddle
Related
I have 3 columns in Invoice table.
InvoicePeriod
InvoiceType
Fees
I have data like this:
InvoicePeriod InvoiceType Fees
2020-06-30 ABC 10.0
2020-06-30 ABC 40.0
2020-06-30 ABC 32.0
2020-09-30 ABC 5.0
2020-09-30 XYZ 30.0
2020-12-31 ABC 20.0
2020-12-31 ABC 10.0
2021-01-31 XYZ 60.0
2021-02-01 DEF 36.0
Now I want the last(max) of invoice period of each invoice type and the summation of fees of previous dates.
Output:
InvoicePeriod InvoiceType Fees
2020-12-31 ABC 87.0
2021-01-31 XYZ 30.0
2021-02-01 DEF 0.0
How can I achieve this?
Thanks,
Ankit
You want to group by InvoiceType (since you want one row per type) and you want the aggregate functions max and sum to combine values within those groups.
So
SELECT MAX(InvoicePeriod), InvoiceType, SUM(Fees)
FROM mytable
GROUP BY InvoiceType
Edited to exclude the fees that match the max date, now that I understand the problem better:
SELECT t2.MaxPeriod, t2.InvoiceType, SUM(CASE WHEN t1.InvoicePeriod < t2.MaxPeriod THEN t1.Fees ELSE 0 END)
FROM test t1 INNER JOIN
(
SELECT MAX(InvoicePeriod) MaxPeriod, InvoiceType
FROM test
GROUP BY InvoiceType
) t2 ON t1.InvoiceType = t2.InvoiceType
GROUP BY t2.MaxPeriod, t2.InvoiceType
There are different ways of doing this, but I think the above does what you want so you could build off of it. The inner query gets the max InvoicePeriod for each InvoiceType. The outer query uses that and also sums the Fees when the date is less than the max for that group.
I think this is what you're looking for.
SELECT
MAX(in_main.InvoicePeriod) AS InvoicePeriod
, InvoiceType
/* Subtract out fees on last invoice date*/
, SUM(Fees) - (
SELECT COALESCE(SUM(Fees), 0)
FROM Invoice in_sub
WHERE (
in_sub.InvoiceType = in_main.InvoiceType
AND
in_sub.InvoicePeriod = MAX(in_main.InvoicePeriod)
)
) AS Fees
FROM Invoice in_main
GROUP BY InvoiceType
http://sqlfiddle.com/#!18/288adf/2/0
Steps:
Aggregate per period and type.
Get the sum of a type's previous periods.
Use TOP WITH TIES in combination with ROW_NUMBER in order to keep all types' last periods.
The query:
select top(1) with ties
invoiceperiod,
invoicetype,
coalesce(sum(sum(fees)) over (
partition by invoicetype
order by invoiceperiod
rows between unbounded preceding and 1 preceding
), 0.0) as sum_fees
from invoice
group by invoiceperiod, invoicetype
order by row_number() over (partition by invoicetype order by invoiceperiod desc);
Demo: https://dbfiddle.uk/?rdbms=sqlserver_2019&fiddle=6a651f85961b27be687026c2ce73c8f9
I have this query:
SELECT
COUNT(DISTINCT ProdTr.OrdNo) AS Orders,
ProdTr.YrPr AS Period,
SUM(ProdTr.DAm) AS Total,
SUM(ProdTr.IncCst) AS Cost
FROM ProdTr
WHERE ProdTr.TrTp = 1 AND ProdTr.CustNo != 0
AND ProdTr.YrPr BETWEEN (201901) AND (201912)
GROUP BY ProdTr.YrPr
ORDER BY ProdTr.YrPr ASC
And it works well. It yields the expected result, sales data from the date period 2019-01 to 2019-12. Result:
I would like to add an extra column that shows the same data - but from last year. For period 2019-01 it should show sales data for 2018-01 (1 year back). I managed to do this with a subquery, but it is slow - and seems like a bad idea.
Are there any better ways to achieve this? Database version is MSSQL 2016.
Thank you very much for your time.
You can do it with conditional aggregation:
SELECT
COUNT(DISTINCT CASE WHEN LEFT(YrPr, 4) = '2019' THEN OrdNo END) AS Orders2019,
'2019' + RIGHT(YrPr, 2) AS Period2019,
SUM(CASE WHEN LEFT(YrPr, 4) = '2019' THEN DAm END) AS Total2019,
SUM(CASE WHEN LEFT(YrPr, 4) = '2019' THEN IncCst END) AS Cost2019,
SUM(CASE WHEN LEFT(YrPr, 4) = '2018' THEN DAm END) AS Total2018
FROM ProdTr
WHERE TrTp = 1 AND CustNo != 0
AND YrPr BETWEEN (201801) AND (201912)
GROUP BY RIGHT(YrPr, 2)
ORDER BY Period2019 ASC
You could do it like this:
WITH TwoYears AS (
SELECT COUNT(DISTINCT ProdTr.OrdNo) AS Orders
, ProdTr.YrPr AS Period
, SUM(ProdTr.DAm) AS Total
, SUM(ProdTr.IncCst) AS Cost
FROM ProdTr
WHERE ProdTr.TrTp = 1
AND ProdTr.CustNo != 0
AND ProdTr.YrPr BETWEEN 201801 AND 201912
GROUP BY ProdTr.YrPr
), CurrentYear AS (
SELECT Orders, Period, Total, Cost
FROM TwoYears
WHERE Period >= 201901
), PreviousYear AS (
SELECT Orders, Period, Total, Cost
FROM TwoYears
WHERE Period < 201901
)
SELECT c.Orders, c.Period, c.Total, c.Cost
, p.Orders AS PrevOrders, p.Period AS PrevPeriod, p.Total AS PrevTotal, p.Cost AS PrevCost
FROM CurrentYear c
FULL JOIN PreviousYear p ON p.Period = c.Period - 100
ORDER BY COALESCE(c.Period, p.Period + 100)
I have the below table structure and I need to assign a number to each customer, in a descending way, based on the total quantity purchased:
customerid order_date item quantity price
10330 2016-06-30 Skateboard 1 28.00
10101 2016-06-30 Raft 1 58.00
10298 2016-07-01 Skateboard 1 33.00
10101 2016-07-01 Snow Shoes 4 125.00
10299 2016-07-06 Parachute 1 1250.00
10339 2016-07-27 Umbrella 1 4.500
10449 2016-08-13 Bicycle 1 180.790
10439 2016-08-14 Ski Poles 2 25.500
What I have tried so far is the below query but it still does not to seem right:
SELECT *, ROW_NUMBER() OVER(PARTITION BY customerid ORDER BY sum(quantity) DESC) FROM IMP_MyTablee
GROUP BY customerid, order_date, item, quantity, price
Can anyone tipe me off? Thanks
Desired output
I need to see the CustomerID once no matter how many records are and the total quantity purchased and also to be ranked:
customerid order_date item quantity price rank
10330 2016-06-30 Skateboard 5 28.00 1
10101 2016-06-30 Raft 3 58.00 3
10298 2016-07-01 Skateboard 4 33.00 2
Try this. First group and then rank
with A as (
select * from
( values
(10330, '2016-06-30', 'Skateboard', 1, 28.00),
(10101, '2016-06-30', 'Raft' , 1, 58.00),
(10298, '2016-07-01', 'Skateboard', 1, 33.00),
(10101, '2016-07-01', 'Snow Shoes', 4, 125.00),
(10299, '2016-07-06', 'Parachute' , 1, 1250.00),
(10339, '2016-07-27', 'Umbrella' , 1, 4.500),
(10449, '2016-08-13', 'Bicycle' , 1, 180.790),
(10439, '2016-08-14', 'Ski Poles' , 2, 25.500)
) as T(customerid, order_date, item, quantity, price)
)
, B as (
select
customerid,
item,
sum(quantity) as total,
price
from
A
group by
customerid, item, price
)
select top(3) *, ROW_NUMBER() over (order by total desc) from B order by total desc
Your specifications call for a query like this:
SELECT customerid,
SUM(Quantity) As Qty
ROW_NUMBER() OVER (GROUP BY customerid ORDER BY Sum(Quantity) desc) As Rank
FROM IMP_MyTablee
GROUP BY customerid
If you need detail as well, you need to specify what detail you need - SUM(price * Quantity), or MIN(order_date), or whatever....
I have 2 tables
OrderDetails:
Id Name type Quantity
------------------------------------------
2009 john a 10
2009 john a 20
2010 sam b 25
2011 sam c 50
2012 sam d 30
ValueDetails:
Id Value
-------------------
2009 300
2010 500
2011 200
2012 100
I need to get an output which displays the data as such :
Id Name type Quantity Price
-------------------------------------------------
2009 john a 10
2009 john a 20 9000
2010 sam b 25
2011 sam c 50
2012 sam d 30 25500
The price is calculated by Value x Quantity and the sum of the values is displayed in the last repeating row of the given Name.
I tired to use sum and group by but I get only two rows. I need to display all 5 rows. How can I write this query?
You can use Row_Number with max of Row_Number to get this formatted sum
;with cte as (
select od.*, sm= sum( od.Quantity*vd.value ) over (partition by Name),
RowN = row_number() over(partition by Name order by od.id)
from #yourOrderDetails od
inner join #yourValueDetails vd
on od.Id = vd.Id
)
select Id, Name, Type, Quantity,
case when max(RowN) over(partition by Name) = row_number() over(partition by Name order by Id)
then sm else null end as ActualSum
from cte
Your input tables:
create table #yourOrderDetails (Id int, Name varchar(20), type varchar(2), Quantity int)
insert into #yourOrderDetails (Id, Name, type, Quantity) values
(2009 ,'john','a', 10 )
,(2009 ,'john','a', 20 ) ,(2010 ,'sam ','b', 25 )
,(2011 ,'sam ','c', 50 ) ,(2012 ,'sam ','d', 30 )
create table #yourValueDetails(Id int, Value Int)
insert into #yourValueDetails(Id, value) values
( 2009 , 300 ) ,( 2010 , 500 )
,( 2011 , 200 ) ,( 2012 , 100 )
SELECT a.ID,
a.Name,
a.Type,
a.quantity,
price = (a.quantity * b.price)
FROM OrderDetails a LEFT JOIN
ValueDetails b on a.id = b.id
This will put the price on every row. If you want to do a SUM by Id,Name and Type it's not going to show the individual records like you show them above. If you want to put a SUM on one of the lines that share the same Id, Name and Type then you'd need a rule to figure out which one and then you could probably use a CASE statement to decide on which line you want to show the SUM total.
I have a table
AvailbilityDate | Resort | AccomName | Price | Min Occupancy
24 June 2012 | Resort1 | Accom1 | 999 | 8
24 June 2012 | Resort1 | Accom2 | 888 | 6
24 June 2012 | Resort2 | Accom1a | 243 | 10
24 June 2012 | Resort2 | Accom2a | 563 | 7
What I currently have is
SELECT AvailbilityDate, Resort, MIN(Price) AS Lowest
FROM mytable
GROUP BY AvailbilityDate, Resort
I want to be able to get the AccomName and the Min Occupancy
Many thanks in advance
With standard ANSI SQL, the solution would be this:
SELECT *
FROM (
SELECT AvailbilityDate,
resort,
accomName,
price,
min_occupancy,
min(price) over (partition by AvailbilityDate, Resort) as min_price
FROM deals_panel_view
) t
WHERE min_price = price;
Should work on PostgreSQL, Oracle, DB2, SQL Server, Sybase and Terradata
Using a common table expression and Ranking functions you can do this
WITH cte as (
SELECT
ROW_NUMBER() over (PARTITION BY AvailabilityDate,Resort ORDER BY price) as row,
AvailbilityDate,
Resort,
AccomName,
Price,
[Min Occupancy]
FROM mytable
)
SELECT AvailbilityDate,Resort,Price,AccomName,[Min Occupancy] from cte where row=1
SELECT AvailbilityDate, Resort, AccomName, "Min Occupancy", MIN(Price) AS Lowest
FROM mytable
GROUP BY AvailbilityDate, Resort
You can do this in several ways.
1) Ranking - per a_horse_with_no_name's solution
2) Group by and Cross Apply. Essentially plug the columns you want to group up in the first subquery and then all other columns go into the second subquery. Use an Order By in the second subquery to deal with any column you want to apply MIN (or MAX) to.
SELECT a.AvailbilityDate,
a.resort,
b.AccomName,
b.min_occupancy,
b.Lowest
FROM
(
SELECT t1.AvailbilityDate, t1.resort
FROM myTable t1
GROUP BY t1.AvailbilityDate, t1.resort
) a
CROSS APPLY
(
SELECT TOP 1 t2.AccomName, t2.min_occupancy, t2.price as Lowest
FROM mytable t2
WHERE t2.AvailbilityDate = a.AvailbilityDate
AND t2.resort = a.resort
ORDER BY t2.price ASC
) b
3) Use subqueries in select statement (not very elegant but works) with Group By. This is assuming that there is only one accomName with the given minimum price for each combination of AvailbilityDate and resort.
SELECT a.AvailbilityDate,
a.resort,
(SELECT accomName FROM myTable t1
WHERE t1.AvailbilityDate = a.AvailbilityDate
AND t1.resort = a.resort
AND t1.price = MIN(a.price)
) as accomName,
(SELECT min_occupancy FROM myTable t1
WHERE t1.AvailbilityDate = a.AvailbilityDate
AND t1.resort = a.resort
AND t1.price = MIN(a.price)
) as min_occupancy,
MIN(a.price) as Lowest
FROM myTable a
GROUP BY a.AvailbilityDate, a.resort
SELECT AccomName, MIN([Min Occupancy]) AS Lowest FROM mytable GROUP BY AccomName
That would give you ONLY the desired Infos. If you want to have the desired fields in ADDITION to what you have already, it would be like:
SELECT AvailbilityDate, AccomName, Resort, MIN(Price) AS Lowest, Min([Min Occupancy]) As LowestMinOcc FROM mytable GROUP BY AvailbilityDate , AccomName , Resort