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
)
Related
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.
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
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;
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 years ago.
Improve this question
I have the following tables:
Training Occurrence
Id Training Id Due Date
5 1 09/01/2018
6 1 09/15/2018
7 2 09/01/2018
Training Occurrence User
Id Training Material Occurrence Id User Id
1 5 'Chad'
2 5 'Chad'
3 6 'Chad'
4 6 'Chad'
5 7 'Chad'
My query needs to get the newest Training Material Occurrence User record of the newest Training Material Occurrence table. So if I pass in the user 'Chad'
I would want to see:
Id Occurrence Id User Training Id Due Date
4 6 'Chad' 1 09/15/2018
5 7 'Chad' 2 09/01/2018
Here is my query:
SELECT tmou.*, tmo.TrainingMaterialId, tmo.DueDate
FROM dbo.TrainingMaterialOccurrenceUser as tmou
INNER JOIN dbo.TrainingMaterialOccurrence as tmo on
tmou.TrainingMaterialOccurrenceId = tmo.Id
AND tmou.Id IN (SELECT MAX(tmou.Id)
FROM dbo.TrainingMaterialOccurrenceUser as tmou
WHERE tmou.UserId = #UserId
AND tmou.TrainingMaterialOccurrenceId IN (SELECT MAX(tmo.Id) as occurrenceId
FROM dbo.TrainingMaterialOccurrence as tmo
WHERE tmo.Id IN (Select TrainingMaterialOccurrenceId FROM dbo.TrainingMaterialOccurrenceUser as tmou1 WHERE tmou1.UserId = #UserId)
GROUP BY tmo.TrainingMaterialId)
GROUP BY tmou.TrainingMaterialOccurrenceId)
As you can see this is a mess. Any ideas on how I can clean this up.
Rank your rows with ROW_NUMBER:
SELECT Id, TrainingMaterialOccurrenceId, UserId, TrainingMaterialId, DueDate
FROM
(
SELECT
tmou.Id,
tmou.TrainingMaterialOccurrenceId,
tmou.UserId,
tmo.TrainingMaterialId,
tmo.DueDate,
ROW_NUMBER() OVER(PARTITION BY tmo.TrainingMaterialId
ORDER BY tmo.DueDate DESC,
tmo.Id DESC,
tmou.TrainingMaterialOccurrenceId DESC,
tmou.Id DESC) AS rn
FROM dbo.TrainingMaterialOccurrenceUser as tmou
INNER JOIN dbo.TrainingMaterialOccurrence as tmo
ON tmo.Id = tmou.TrainingMaterialOccurrenceId
)
WHERE rn = 1;
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
Closed 8 years ago.
Improve this question
I have a table with truck and locations , each truck can have many records with each location:
ex:
truck | location
----------------
60111 | 1
60111 | 2
60111 | 3
60111 | 4
60222 | 1
60222 | 2
....etc
I want to select the trucks with ONLY locations in (1,2).
in my example the return must be 60222 ONLY
how to do this?
Note: I want a dynamic solution not hard coded.
A solution similar to the one of Patrick Hofman is to move the logic in the HAVING clause
SELECT truck
FROM table
GROUP BY truck
HAVING COUNT(DISTINCT location) = 2
AND SUM(CASE WHEN location IN (1, 2) THEN 0 ELSE 1 END) = 0
The first condition return the truck with only two distinct location, not checking their values, the second condition force those location to be 1 and 2
This will select trucks that have exactly locations 1 and 2:
select t1.truck
from truck_location t1
where t1.location in (1, 2)
group by truck
having count(distinct t1.location) = 2
and count(distinct t1.location) = (select count(*)
from truck_location t2
where t2.truck = t1.truck);
The distinct inside the count() is only necessary if a truck could be assigned to the same location twice. If the combination truck/location is guaranteed to be unique this is not necessary.
SQLFiddle: http://sqlfiddle.com/#!15/b865f/1
select distinct truck
from
my_table
where
truck not in
(
select distinct truck
from my_table
where location not in (1, 2)
)
You can group by the truck, filter on the location and check the result is 2:
select truck
from table
where location in (1, 2)
group
by truck
having count(distinct location) = 2