How to use group by with case statement [closed] - sql

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 11 months ago.
Improve this question
I have a table with following fields
CREATE TABLE Tblstock
( ID int , SlNo int, Storage varchar(10), stock int);
insert into Tblstock values
(1, 1, 'STORE', 100),
(2, 1, 'Floor 1', 20),
(3, 2, 'STORE', 2000),
(4, 2, 'Floor 1', 40);
I have to dynamically update the left over quantity in store after it got consumed on floor1, I have written a code to calculate qty in store using below mentioned query,
SELECT (
(SELECT CASE WHEN COUNT(B.SlNo) > 1 OR B.Storage = 'STORE' THEN SUM(B.Stock)END FROM TblStock B GROUP BY B.SlNo) -
(SELECT CASE WHEN COUNT(B.SlNo) > 1 OR B.Storage <> 'STORE' THEN SUM(B.Stock)END FROM TblStock B GROUP BY B.SlNo))
However it is not generating the desired result and throwing error
Can anybody help to write it properly so that I get single value of remaining quantity in store

You just need a straight-forward grouping and conditional aggregation
SELECT
s.SlNo,
Total = SUM(CASE WHEN s.Storage = 'STORE' THEN s.Qty ELSE -s.Qty END)
FROM TblStock s
GROUP BY
s.SlNo;
db<>fiddle

Assuming what you are trying to do is to deduct the quantity (qty) in storage called store by the sum of the rest of the other storage. I could think of a query like this:
select *,
(Qty - (select sum(b.Qty) from tblstock as b
where b.Storage <> 'store'
and b.SINo = a.SINo
group by b.SINo)) as remainingQty
from tblstock as a
where a.Storage = 'store' group by a.SINo
The query above, with the following input:
ID
SINo
Storage
Qty
1
1
store
100
2
1
floor 1
20
3
1
floor 2
30
4
2
store
100
5
2
floor 1
40
6
2
floor 2
50
It produces the following output:
ID
SINo
Storage
Qty
remainingQty
1
1
store
100
50
4
2
store
100
10
You can find the SQLFiddle here.
Note:
If you are want to avoid subquery and have the urge to chug in join fiddle:
select a.id,
a.SINo,
a.Storage,
a.Qty,
c.Qty,
(a.Qty - c.Qty) as remainingQty
from tblstock as a
join
(select b.SINo,
sum(b.Qty) as Qty
from tblstock as b
where b.Storage <> 'store'
group by b.SINo) as c
on c.SINo = a.SINo
where a.Storage = 'store' group by a.SINo

Related

How to get sum of amounts from raw data having specific labels set [duplicate]

This question already has answers here:
Group and sum row data into columns in MS-SQL?
(2 answers)
Closed 1 year ago.
I have a table in sql like below:
Code Label Amount
X this 100
X this 300
X this 500
X last 700
X last 800
The expected output is:
Code ThisAmount LastAmount
X 900 1500
I've tried below but didn't work as expected:
select t.code, sum(t2.amount) ThisAmount, sum(t3.amount) LastAmount
from table t
inner join table t2 on t.code=t2.code and t2.label='this'
inner join table t3 on t.code=t3.code and t2.label='last'
group by t.code
Can you please help?
Thanks
you need to use conditional aggregation:
select
t.code
, sum(case when Label = 'this' then amount end) ThisAmount
, sum(case when Label = 'last' then amount end) LastAmount
from table t
group by t.code

Case in Sql group by query

I am working on a project in which I want to use Case to calculate price of product under specific Reference Number in SQL server. Below is my Sql query
SELECT
product AS Products,
refNum AS Refrence,
COUNT(id) AS Count
FROM ProductPriceList
GROUP BY
refNum, product
By Executing Above query I get:
Product Reference Count
Product1 Ref08 24
Product2 Ref08 7
Product3 Ref07 32
Product2 Ref12 1
Product3 Ref12 18
Product1 Ref07 76
Product1 Null 56
Can anyone guide me how to use Case statement in Sql query with group by statement to show price Below is the case:
if count < 10 then price 1
if count > 10 and < 100 then price 2
if count > 100 then price 3
I don't want to add a new table in my database. I hope you can understand my query.
Thanks in advance.
I think a basic CASE expression can handle your requirement:
SELECT
product AS Products,
refNum AS Refrence,
CASE WHEN COUNT(*) < 10 THEN 1
WHEN COUNT(*) >= 10 AND COUNT(*) < 100 THEN 2
ELSE 3 END AS price
FROM ProductPriceList
GROUP BY
product, refNum;
Not much to explain here, except that the 2 price case uses a bound which includes the count of 10 (since the 1 price case excludes it).
Here's alternative (doesn't differ much from exisiting one though):
You can use your query in subquery and use case outside:
select product,
--to get NULL values back
case Reference when 'RefNull' then NULL else Reference end [Reference],
case when [Count] < 10 then 1
when [Count] between 10 and 100 then 2
else 3 end [price]
from (
SELECT product AS Products,
--to allow also null values to be grouped
coalesce(refNum, 'RefNull') AS Refrence,
COUNT(id) AS Count
FROM ProductPriceList
GROUP BY coalesce(refNum, 'RefNull'), product
) [a]
Dataset:
Create Table ProductPriceList
(
Product varchar(10)
,RefNum CHAR(5)
,Records Int
);
Insert into ProductPriceList
Values
('Product1','Ref08',24)
,('Product2','Ref08',7)
,('Product3','Ref07',32)
,('Product2','Ref12',1)
,('Product3','Ref12',18)
,('Product1','Ref07',76)
,('Product1', NULL, 56);
With RCTE AS
(
Select Product
,RefNum
,Records
,1 RowNo
From ProductPriceList PPL
Union All
Select Product
,RefNum
,Records
,RowNo + 1
From RCTE R
Where RowNo + 1 < Records
)
Insert Into ProductPriceList (Product, RefNum, Records)
Select Product, RefNum, Records
From RCTE
where Records > 1
Query to fetch desired result:
Select Product
,RefNum
,Case When Count(*) < 10 Then 1
When Count(*) Between 10 and 99 then 2
Else 3 End Price
From ProductPriceList
Group By Product, RefNum
SQL Fiddle

SELECT/NOT EXISTS unique records with a 'condition' [duplicate]

This question already has answers here:
sql query to extract unique records
(4 answers)
Closed 7 years ago.
My table contains only 2 columns ID and product and looks like this:
ID Product
-----------------
1 microsoft
0 cisco
2 cisco
7 cisco
3 vmware
0 adobe
0 microsoft
I need to write a query that lists records having id=0 only,
ID Product
---------------
0 adobe
The reason I do not want to list
ID Product
----------------
0 micrsoft
0 cisco
is because they have one or more records which does have a product ID.
Tried this:
SELECT
[ProductID], [Product]
FROM [table] AS t1
WHERE ProductID = 0
AND NOT EXISTS (SELECT 1
FROM [table] AS t2
WHERE t1.ProductID = t2.ProductID
AND t2.ProductID <> 0)
seems to take a long time to query. (table has 2 000 000 records)
Use a simple group by with a having clause:
select 0 as id, product
from [table] t
group by product
having min(id) = 0 and max(id) = 0;
You just need to join on Product instead of ProductID:
SELECT [ProductID],[Product]
FROM [table] as t1
where ProductID=0
AND NOT EXISTS (
SELECT 1 FROM [table] AS t2
where t1.Product=t2.Product
AND t2.ProductID<>0
)
This translates to "where there exists no other row where the product has the same name, with an ID other than 0".

How do I aggregate numbers from a string column in SQL

I am dealing with a poorly designed database column which has values like this
ID cid Score
1 1 3 out of 3
2 1 1 out of 5
3 2 3 out of 6
4 3 7 out of 10
I want the aggregate sum and percentage of Score column grouped on cid like this
cid sum percentage
1 4 out of 8 50
2 3 out of 6 50
3 7 out of 10 70
How do I do this?
You can try this way :
select
t.cid
, cast(sum(s.a) as varchar(5)) +
' out of ' +
cast(sum(s.b) as varchar(5)) as sum
, ((cast(sum(s.a) as decimal))/sum(s.b))*100 as percentage
from MyTable t
inner join
(select
id
, cast(substring(score,0,2) as Int) a
, cast(substring(score,charindex('out of', score)+7,len(score)) as int) b
from MyTable
) s on s.id = t.id
group by t.cid
[SQLFiddle Demo]
Redesign the table, but on-the-fly as a CTE. Here's a solution that's not as short as you could make it, but that takes advantage of the handy SQL Server function PARSENAME. You may need to tweak the percentage calculation if you want to truncate rather than round, or if you want it to be a decimal value, not an int.
In this or most any solution, you have to count on the column values for Score to be in the very specific format you show. If you have the slightest doubt, you should run some other checks so you don't miss or misinterpret anything.
with
P(ID, cid, Score2Parse) as (
select
ID,
cid,
replace(Score,space(1),'.')
from scores
),
S(ID,cid,pts,tot) as (
select
ID,
cid,
cast(parsename(Score2Parse,4) as int),
cast(parsename(Score2Parse,1) as int)
from P
)
select
cid, cast(round(100e0*sum(pts)/sum(tot),0) as int) as percentage
from S
group by cid;

Group By from two tables [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have a requirement to show a report in the following format from the two different tables as shown below, the below report should count the order numbers by branch.
===================================================================
Branch OrdersCountInTable1 OrdersCountInTable2
===================================================================
100 5 2
200 10 10
300 12 11
how can i achieve this using a sqlquery?
Following are the columns in the tables:
Table1:
________
- Branch
- OrderNo
Table2
__________
- Branch
- OrderNo
Table1 Data:
===============================
Branch OrderNo
===============================
100 1000
100 1001
200 2001
100 1003
Table2 Data:
===============================
Branch OrderNo
===============================
100 1000
200 2001
100 1003
We just want to reconcile orders from both the tables!!
Thanks for any valuable feedbacks.
One more or less generic way to do it
SELECT COALESCE(t1.branch, t2.branch) branch,
COALESCE(t1.ordercount, 0) OrdersCountInTable1,
COALESCE(t2.ordercount, 0) OrdersCountInTable2
FROM
(
SELECT branch, COUNT(orderno) ordercount
FROM Table1
GROUP BY branch
) t1 FULL JOIN
(
SELECT branch, COUNT(orderno) ordercount
FROM Table2
GROUP BY branch
) t2
ON t1.branch = t2.branch
Assumption is that tables may not have entries for all branches. That's why FULL JOIN is used.
Do like this using SUM aggregate function and UNION ALL operator
SELECT Branch,
SUM( CASE tag WHEN 'table1' THEN 1 ELSE 0 END) as OrdersCountInTable1,
SUM( CASE tag WHEN 'table2' THEN 1 ELSE 0 END) as OrdersCountInTable2
FROM
(
SELECT Branch,'table1' as tag
FROM Table1
UNION ALL
SELECT Branch,'table2' as tag
FROM Table2
) z
GROUP BY Branch
ORDER BY Branch
Try it with a union nested query:
select
Branch, count(Orders1) OrdersCountInTable1, count(Orders2) OrdersCountInTable2
from (
select Branch,OrderNo Orders1,NULL Orders2 from Table1
union
select Branch,NULL Orders1,OrderNo Orders2 from Table2
) t
group by Branch