SQL SUM aggragete issue - sql

ID Title Qty
1 BMW 2
2 VW 3
I want in one SQL query to find a sum of quantity and divide it by current Qty.
For example:
SUM (Qty) = 5, so I want to compute scores by formula. 2/5 and 3/5
ID title newscores
1 BMW 2/5
1 vW 2/5

Demo
SELECT id
,title
,qty/(select sum(qty) from cars)
FROM cars
GROUP BY id

this should work
select title , sum (QTY) , t2.total, sum(QTY) / t2.total
from table , (select sum(QTY) as total from table) as t2
group by title

SELECT ID, Title, CONCAT( Qty, '/', (SELECT SUM( Qty) FROM table1) ) AS 'newscores'
FROM `table1`

select id, title, qty/(select sum(qty) from make)
from make
See SQLFiddle.
Note there is no need whatsoever for a group by clause.

Related

SQL Server : SELECT Highest Price and add qty's from table

I have the following table TableAllProds:
ProdName ManuPartNo Price Qty Supplier
--------------------------------------------------
Part1 R10001 100.00 2 Supp1
Part2 R10002 500.00 2 Supp2
Part3 R30023 50.00 1 Supp3
Part2again R10002 100.00 5 Supp4
Part2Again R10002 300.00 10 Supp5
Part1again R10001 200.00 5 Supp3
I have a select statement to bring me back the highest price which works fine if there are duplicate products from different suppliers.
SELECT
ProdName, ManuPartNo, Price, Qty, Supplier
FROM
(SELECT
dbo.TableAllProds.*,
ROW_NUMBER() OVER (PARTITION BY ManuPartNo ORDER BY Price ASC) AS RN
FROM
dbo.TableAllProds) AS t
WHERE
RN = 1
ORDER BY
ManuPartNo
However I would also like to total all of the qty's for all suppliers Example for ManuPartNo - R10001 I would Like to return R10001 - 200.00 - 7(qty) and the supplier of the highest Price if possible.
Not sure how to google this, I can either return the highest/Lowest price easily and also return a sum of the qty for each part but am not sure about how to perform both queries at once.
Thanks for any help.
You can use SUM as a windowed function:
SELECT ProdName, ManuPartNo, Price, Qty, TotalQty, Supplier
FROM ( SELECT *,
ROW_NUMBER() OVER(PARTITION BY ManuPartNo ORDER BY Price ASC) AS RN,
SUM(Qty) OVER(PARTITION BY ManuPartNo) AS TotalQty,
FROM dbo.TableAllProds) AS t
WHERE RN = 1
ORDER BY ManuPartNo;
This seems to be what you want... uncomment the where clause if you only want that supplier.
declare #TableAllProds table (ProdName varchar(16), ManuPartNo varchar(16), Price decimal (5,2), Qty int, Supplier varchar(16))
insert into #TableAllProds
values
('Part1','R10001',100.00,2,'Supp1'),
('Part2','R10002',500.00,2,'Supp2'),
('Part3','R30023',50.00,1,'Supp3'),
('Part2again','R10002',100.00,5,'Supp4'),
('Part2Again','R10002',300.00,10,'Supp5'),
('Part1again','R10001',200.00,5,'Supp3')
;WITH CTE AS(
SELECT
ProdName,
ManuPartNo,
Price,
Supplier,
sum(Qty) over (partition by ManuPartNo) TotalOverAllSuppliers,
case when Price = max(price) over (partition by ManuPartNo) then Supplier end HighestPricedSupplier
FROM
#TableAllProds)
select
*
from cte
--where HighestPricedSupplier is not null
SELECT a.ManuPartNo, a.Price, a.QTY, b.Supplier
FROM (SELECT t1.ManuPartNo, MAX(t1.Price) AS Price, SUM(t1.Qty) AS QTY
FROM dbo.alltableprods t1
GROUP BY t1.ManuPartNo) a
JOIN (SELECT t2.ManuPartNo, t2.price, T2.Supplier,
ROW_NUMBER() OVER (PARTITION BY t2.ManuPartNo ORDER BY t2.price desc)
AS RN
FROM dbo.alltableprods t2
GROUP BY t2.ManuPartNo, t2.Price, t2.Supplier) b ON a.ManuPartNo =
b.ManuPartNo
WHERE b.RN = 1
Using this will return
R10001 200.00 7 Supp3
R10002 500.00 17 Supp2
R30023 50.00 1 Supp3
I have a question though. Is it possible for there to be more than one supplier that has the same part at the same price? If so then this will still work however it will just grab whatever applicable supplier it finds first.
You can query using row_number as below:
Select * from (
Select *, RowN = Row_Number() over(Partition by ManuPartNo order by Price desc), SmQty = Sum(Qty) over(Partition by ManuPartNo) from dbo.TableAllProds ) a
where a.RowN = 1

Select max value in subquery in SQL

I have a query like below:
select *
from
(select
centre_name, sum(qty) as number1
from
(select
exchange_from_centre_id as cenid,
count(exchange_from_centre_id) as qty
from
as2.exchange
group by
exchange_from_centre_id
union all
select
exchange_to_centre_id as cenid,
count(exchange_to_centre_id) as qty
from
as2.exchange
group by
exchange_to_centre_id), as2.centre c
where
c.centre_id = cenid
group by
centre_name);
and this is the result: Name of the centre and the number of exchange
Alice Springs Desert Park 1
Werribee Open Range Zoo 6
Kruger National Park 2
Johannesburg Zoo 4
Australia Zoo 2
SanWild Wildlife Sanctuary 5
I like to select the max value from this result (the 2nd row), beside sorting and choosing the 1st row, could anyone help me with the MAX query.
that should work
select * from (select centre_name, sum(qty) as number1 from
(select exchange_from_centre_id as cenid, count(exchange_from_centre_id) as qty
from as2.exchange
group by exchange_from_centre_id
union all
select exchange_to_centre_id as cenid, count(exchange_to_centre_id) as qty
from as2.exchange
group by exchange_to_centre_id), as2.centre c
where c.centre_id = cenid
group by centre_name) where number1 = (select max(number1) from (select centre_name, sum(qty) as number1 from
(select exchange_from_centre_id as cenid, count(exchange_from_centre_id) as qty
from as2.exchange
group by exchange_from_centre_id
union all
select exchange_to_centre_id as cenid, count(exchange_to_centre_id) as qty
from as2.exchange
group by exchange_to_centre_id), as2.centre c
where c.centre_id = cenid
group by centre_name));
SQL Fiddle Demo
I use your result query instead of the big query to simplify the sample.
I update your sample to have 2 row with max value 6.
You calculate in a select the max value, and then join to the original table to bring all row matching that value
SELECT *
FROM (SELECT MAX(Score) Score
FROM Table1) as mV
INNER JOIN Table1 t
ON mv.Score = t.Score

Counting Values based on distinct values from another Column

I need to calculate how many orderlines there are based on the orderlineNo being distinct. Each OrderNo is different BUT the OrderLineNo is the same for each order.
i.e. 9 lines on a order then order lines number will go from 1 - 9. The same if on another order there are 3 orderlines they will go from 1 - 3
But in orderlineno there could be orderline numbers that are the same - for this I only want to count it once
Example:
OrderNo OrderLineNo
987654 1
987654 2
987654 2
987654 3
987654 4
987654 5
987654 6
987654 7
The total order lines here is 7. There are two order lines with 2 and I want them to only be counted once.
Is this possible using SQL Server 2014.
You can add DISTINCT to a COUNT:
select OrderNo, count(distinct OrderLineNo)
from tab
group by OrderNo;
Or if OrderLineNo always starts with 1 and increases without gaps:
select OrderNo, max(OrderLineNo)
from tab
group by OrderNo;
Edit:
Based on the comment it's not a count per OrderNo, but a global count. You need to use a Derived Table:
select count(*)
from
(select distinct OrderNo, OrderLineNo
from tab
) as dt;
or
select sum(n)
from
(select OrderNo, max(OrderLineNo) as n
from tab
group by OrderNo
) as dt;
or
select sum(Dist_count)
from
( select OrderNo,count(distinct OrderLineNo) as Dist_count
from Table1
group by OrderNo
) as dt
I guess you want this:
SELECT OrderNo, COUNT(distinct OrderLineNo) as CntDistOrderLineNoPerOrderNo
FROM Table1
GROUP BY OrderNo
demo
So for every OrderNo the count of dictinct OrderLineNo which is 7 for 987654.
If you instead want the sum of all distinct OrderLineNo as commented.
WITH CTE AS
(
SELECT OrderNo,
MAX(OrderLineNo) as MaxOrderLineNoPerOrderNo
FROM Table1
GROUP BY OrderNo
)
SELECT SUM(MaxOrderLineNoPerOrderNo) AS SumOrderLineNoPerOrderNo
FROM CTE
Demo
Use Distinct in count aggregate
select count(distinct OrderLineNo) as Dist_count
from yourtable
A solution without distinct, but it requires applying group by twice:
select orderNo , count(*) from
(select orderNo from tbl group by orderNo,orderlineNo) t1 group by orderNo
Check my answer and modified it as your need:
SELECT DEVICE,
COUNT(CASE WHEN ANOMALY_SEVERITY = 'Critical' THEN 'Critical' END) as 'Critical',
COUNT(CASE WHEN ANOMALY_SEVERITY = 'High' THEN 'High' END) as 'High',
COUNT(CASE WHEN ANOMALY_SEVERITY = 'Medium' THEN 'Medium' END) as 'Medium',
COUNT(CASE WHEN ANOMALY_SEVERITY = 'Low' THEN 'Low' END) as 'Low',
COUNT(CASE WHEN ANOMALY = 'True' THEN 'Total' END) as 'Total'
FROM <table_name> WHERE ANOMALY='True' GROUP BY DEVICE

Calculate total of particular column in sql query

I want to calculate total of particular column
For ex my table must looks like this
Customername Payment id RunningTotal
a 500 5 5
b 500 10 10
c 300 10 7
------ -----------
1300 22
I am getting the table but now I want to calculate the total mentioned at the end for the column Payment and RunningTotal.
If you are getting the above result from table t1, then you can add your sum at the end by using an Union statement. Something like this
select Customername, Payment, id, RunningTotal
from t1
union all
select null,sum(payment),null,sum(runningtotal or any total)
from t1
This will add total payments and the other total at the end of the result.
SELECT Sum(Payment) AS Total FROM tablename;
Output: Total = 1300
select sum(Payment) as SumPayment, sum(RunningTotal) as SumRunningTotal
from yourTable
Without GROUPBY clause use OVER()
Example:
select Customername, sum(Payment) OVER () AS TotalPayment, id, sum(RunningTotal) over()
as RunningTotal
from t1
if you want to sum all rows, its as simple as:
select sum(payment) payment_sum, sum(runningtotal) runningtotal_sum
from customers;
select Customername ,id ,sum(Payment) as Payment , sum(RunningTotal) as RunningTotal from Table group by Customername ,id with rollup

SQL latest record per group with an aggregated column

I have a table similar to this:
STOCK_ID TRADE_TIME PRICE VOLUME
123 1 5 100
123 2 6 150
456 1 7 200
456 2 8 250
For each stock I want to get latest price (where latest is just the max trade_time) and aggregated volume, so for the above table I want to see:
123 6 250
456 8 450
I've just discovered that the current query doesn't (always) work, ie there's no guarantee that the price selected is always the latest:
select stock_id, price, sum(volume) group by stock_id
Is this possible to do without subqueries? Thanks!
As you didn't specify the database you are using Here is some generic SQL that will do what you want.
SELECT
b.stock_id,
b.trade_time,
b.price,
a.sumVolume
FROM (SELECT
stock_id,
max(trade_time) AS maxtime,
sum(volume) as sumVolume
FROM stocktable
GROUP BY stock_id) a
INNER JOIN stocktable b
ON b.stock_id = a.stock_id and b.trade_time = a.maxtime
In SQL Server 2005 and up, you could use a CTE (Common Table Expression) to get what you're looking for:
;WITH MaxStocks AS
(
SELECT
stock_id, price, tradetime, volume,
ROW_NUMBER() OVER(PARTITION BY stock_ID ORDER BY TradeTime DESC) 'RowNo'
FROM
#stocks
)
SELECT
m.StockID, m.Price,
(SELECT SUM(VOLUME)
FROM maxStocks m2
WHERE m2.STock_ID = m.Stock_ID) AS 'TotalVolume'
FROM maxStocks m
WHERE rowno = 1
Since you want both the last trade as well as the volume of all trades for each stock, I don't see how you could do this totally without subqueries, however....
declare #Stock table(STOCK_ID int,TRADE_TIME int,PRICE int,VOLUME int)
insert into #Stock values(123,1,5,100),(123,2,6,150),(456,1,7,200),(456,2,8,250)
Select Stock_ID,Price,(Select sum(Volume) from #Stock B where B.Stock_ID=A.Stock_ID)Volume from #Stock A
where A.Trade_Time=(Select max(Trade_Time) from #Stock)
select a.stock_id, b.price , sum(a.volume) from tablename a
join (select stock_id, max(trade_time), price from tablename
group by stock_id) b
on a.stock_id = b.stock_id
group by stock_id