How to combine or merge columns with NULL in SQL Server? [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 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.

Related

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

Create CASE WHEN labels based on DISTINCT values in a particular column [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 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;

Remove duplicates based on common where condition in sql [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 3 years ago.
Improve this question
Select * from Table_name i am getting below result.
S.no Emp_id Date Description Amount Splitup amount
2667737 12345 8/12/2019 Icecream 50 30
2667738 12345 8/12/2019 Icecream 50 20
2667739 12346 8/12/2019 Chocolate 50 20
But i need the result
S.no Emp_id Date Description Amount Splitup amount
2667737 12345 8/12/2019 Icecream 50 30
2667738 12345 Icecream 20
2667739 12346 8/12/2019 Chocolate 50 20
i need only the first as amount .For same s.no and same emp_id was to have only one date and amount, remaining rows i want to make it empty.
You can consider using lag() windows analytic function :
select [S.no], [Emp_id],
case when lag([Date],1,null) over
(partition by [Date] order by [S.no]) = [Date] then
null
else
[Date]
end as [Date], [Description],
case when lag([Amount],1,null) over
(partition by [Amount] order by [S.no]) = [Amount] then
null
else
[Amount]
end as [Amount], [Splitup amount]
from tab;
Demo
You can use conditional logic with row_number():
select s.s_no, s.emp_id,
(case when row_number() over (partition by emp_id, description order by s_no) = 1
then date
end) as date,
description,
(case when row_number() over (partition by emp_id, description order by s_no) = 1
then amount
end) as amount,
splitup
from t
order by emp_id, s_no;
Note the outer order by and how it matches the conditions in the window clause. SQL result sets are unordered unless there is an explicit order by. If you want the "first" row to have the values, then you need to be sure that the result set is in the right order.

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
)

Totalprice column [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 8 years ago.
Improve this question
Is it possible to create a totalprice column in a table which gets its answer from multiplying 2 values from 2 different tables?
e.g
orderquantity
order_id | product_code | quantity
ordertotalprice
order_id | customer_id | totalprice
products
product_Code | product_name | product_desc | productcost
I want the totalprice column to be = productcost*quantity
To query the totals per order:
SELECT orderquantity.order_id,
SUM(products.productcost * orderquantity.quantity) AS total
FROM orderquantity
INNER JOIN products ON products.product_code = orderquantity.product_code
GROUP BY orderquantity.order_id
Wrap this query in an UPDATE statement to update column totalprice in table ordertotalprice:
UPDATE ordertotalprice
SET totalprice = grouped.total
FROM (
SELECT orderquantity.order_id,
SUM(products.productcost * orderquantity.quantity) AS total
FROM orderquantity
INNER JOIN products ON products.product_code = orderquantity.product_code
GROUP BY orderquantity.order_id
) AS grouped
WHERE ordertotalprice.order_id = grouped.order_id
I am assuming here table ordertotalprice already contains the necessary records. If that is not the case, then you will need an INSERT statement instead of an UPDATE. But then I wonder where to get the customer_id from.