Create CASE WHEN labels based on DISTINCT values in a particular column [closed] - sql

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have data of the following form:
ID
Category
Amount
1
A
100
1
B
200
1
B
150
1
C
500
2
B
20
3
A
100
1
B
100
I wish to GROUP BY the column ID, find out the DISTINCT types of Category present for each ID group and create a new column where I can create the following classification labels for each grouped ID based on the unique or distinct categories present and also calculate the corresponding sum of amount for each grouped ID. So the output should be the follows:
ID
Classification
Sum of Amount
1
ALL
950
1
B only
20
1
A and B only
200
I tried the following SQL code but it doesn't work, most likely because DISTINCT() command within a CASE WHEN statement cannot consider multiple values.
My query:
SELECT
ID,
(CASE WHEN DISTINCT(CATEGORY) IN ("A") then "A Only" WHEN WHEN DISTINCT(CATEGORY) IN ("B") THEN "B only"..........)
SUM(AMOUNT)
FROM Table
GROUP BY 1,2
I have tried multiple ways of using the DISTINCT statement with CASE WHEN but none of them works.

Hmmm . . . How about this?
select id,
(case when min(category) = max(category)
then min(category) || ' only'
when count(distinct category) = 3
then 'All'
when min(category) is NULL
then 'None'
else min(category) || ' and ' || max(category)
end)
from t
group by id;

Related

How to combine or merge columns with NULL in SQL Server? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 months ago.
Improve this question
I'm trying to write a SQL query to take the below data and transform it into the expected result table.
INV
ITEM
Amount
INV123
null
12.00
INV123
null
96.00
INV123
abc
null
INV123
xyz
null
Expected result:
INV
ITEM
Amount
INV123
abc
12.00
INV123
xyz
96.00
Assuming mapping the "first" non-null item to the "first" non-null amount is actually arbitrary, here's one way:
WITH items AS
(
SELECT inv, item, r = ROW_NUMBER() OVER (PARTITION BY inv ORDER BY ##SPID)
FROM dbo.MyTable WHERE item IS NOT NULL
), amounts AS
(
SELECT inv, amount, r = ROW_NUMBER() OVER (PARTITION BY inv ORDER BY ##SPID)
FROM dbo.MyTable WHERE amount IS NOT NULL
)
SELECT inv = COALESCE(items.inv, amounts.inv),
items.item, amounts.amount
FROM items FULL OUTER JOIN amounts
ON items.inv = amounts.inv
AND items.r = amounts.r
ORDER BY COALESCE(items.r, amounts.r);
Working example in this fiddle.
The FULL OUTER JOIN is used because you probably won't always have the same number of non-null items and non-null amounts for a given inv. However you might also want to handle the case where both columns have a non-null value - do those columns stick together on the same output row, or no?
If the ordering needs to be more deterministic, you need to explain what other data exists in the table to allow you to rank those columns. Or if you want alphabetical for item and numerical for amount, just change ORDER BY ##SPID to ORDER BY item/ORDER BY amount respectively.

How to use group by with case statement [closed]

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

How to find unique row other than null for the same ID? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have a below table data which contains status column with null and 'Y' for the ID
Id Name Status
1394 Test 1 Y
1394 Test 2 null
1394 Test 3 null
1395 Test 4 Y
1395 Test 5 Y
1396 test 6 null
ID 1394 contains both null and and Y.
IF ID contains Null then I should not get that ID.
In This case I should get only 1395 because particular ID doesn't contain null value.
You can use not exists:
select t.*
from t
where not exists (select 1
from t t2
where t2.id = t.id and t2.status is null
);
I would use an aggregation approach here:
SELECT Id
FROM yourTable
GROUP BY id
HAVING COUNT(CASE WHEN Status IS NULL THEN 1 END) = 0;
Use conditional aggregation in the HAVING clause:
SELECT Id, MAX(Status) Status
FROM tablename
GROUP By Id
HAVING SUM(CASE WHEN Status IS NULL THEN 1 ELSE 0 END) = 0
Or if you want all the rows and columns use NOT IN:
SELECT *
FROM tablename
WHERE Id NOT IN (SELECT Id FROM tablename WHERE Status IS NULL)
And one more option:
SELECT Id from tablename
EXCEPT
SELECT Id FROM tablename WHERE Status IS NULL;
The first statement gets the set of all ID values. The second gets the set of all ID values where Status is NULL. EXCEPT removes the second set from the first as well as duplicates. Note that there is no ORDER BY clause so do not assume the rows have a defined order. Fiddle

Select rows that if I sum their value = 0 from table [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Let's say I have a table like this:
ID. Location. Value.
1. AGF. 10.00
2. VHJ. -20.00
3. AGF. -20.00
4. AGF. 5.00
5. KLZ. 50.00
6. AGF. 10.00
I want to select the rows that have same Location AND whose Values sum to zero.
In this case the result should be:
1
3
6
because those rows are all in Location AGF and they sum to 0 (10 + -20 + 10).
Try:
Select ID from YourTable where Location IN(
Select location from YouTable
Group By Location
Having sum(Value) = 0
)
You need to find all locations with zero sum using grouping and group filters (group by and having clauses respectively). This can be done in a subquery. Then select all IDs with the just selected locations.
select ID
from YOUR_TABLE
where Location in (
select Location
from YOUR_TABLE
group by Location
having sum(Value) = 0
)
You could use GROUP BY and HAVING, like this:
Select ID from tablelocation where Location IN(
Select location from tablelocation
Group By Location
Having sum(Value) = 0
)

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