Group multiple rows together - sql

I have a table which contains the following and I am looking to group them to get the below output. Is it possible?
Input
ID Value1 Value2 Value3
5 Y NULL NULL
5 NULL 1 NULL
5 NULL NULL USA
5 NULL NULL NULL
6 N NULL NULL
6 NULL 2 NULL
6 NULL NULL GBP
6 NULL NULL NULL
Output
ID Value1 Value2 Value3
5 Y 1 USA
6 N 2 GBP

Group by the id and use max() to get the non-null value per each group
select id,
max(value1) as value1,
max(value2) as value2,
max(value3) as value3
from your_table
group by id
BTW you should think about changing you table design. It is not normalized.

Related

Compare the column values where there are null and not null values

I want to compare the values from a table where there are null and not null values for the same ID ( If not null then I want minimum of two not null values). IF all the values are null for the given ID, I want the values to be displayed as null for the ID.
Input
ID Amount
1 Null
1 Null
1 Null
1 500
1 600
1 700
2 Null
2 Null
2 Null
2 Null
2 Null
3 Null
3 Null
3 300
3 600
3 200
Expected output
ID Amount
1 500 (min Not null value)
2 Null
3 200 (Min Not null value)
Simple grouping will do the trick:
select t.id, min(t.amount)
from table t
group by t.id

Find values which are present in all columns in a Cable

I would like a SQL Server query which finds the Values in a cell which fills multiple columns. For example, if I have table
ID Value1 Value2 Value3
1 2 NULL NULL
1 NULL 3 NULL
1 NULL NULL 4
1 3.4 NULL NULL
2 NULL 3 NULL
2 NULL NULL NULL
3 NULL NULL 91
As in the table above, only 2 of the columns can be filled at a time(First is ID and 2nd is either of Value1, 2 or 3) and ID can be repeated multiple times.
I want to return the ID as only 1 because 1 is the only ID that populates all the three other columns. 2 fills only Value2 and all the other values of 2nd iteration of 2 are NULL where as 3 is present only in Column Value3. Is there someway that I can find the Id's which fill all the other columns.
I would love to do this preferably without a cursor but I can go for cursor if it's compulsory. Thanks
EDIT
Desired Table:
ID
1
The Statement should return only the filtered IDs which populate all the other columns.
Try this
SELECT id,
FROM TableName
GROUP BY id
HAVING MAX(value1) IS NOT NULL AND
MAX(value2) IS NOT NULL AND
MAX(value3) IS NOT NULL
Something for you try if you want some less lines of code:
select ID from dbo.Table_1 group by ID having count(Value1) > 0 AND count(Value2) > 0 AND count(Value3) > 0

SAS: Need to count number of instances per id

Let's assume I have table1:
id value1 value2 value3
1 z null null
1 z null null
1 null y null
1 null null x
2 null y null
2 z null null
3 null y null
3 null null null
3 z null null
id value1 value2 value3
1 z null null
1 z null null
1 null y null
1 null null x
2 null y null
2 z null null
3 null y null
3 null null null
3 z null null
and I have table2:
id
1
2
3
I want to count number of values in each column per id to have output like this. (ex. id 1 has 2 - z's, one y and one x)
id value1 value2 value3
1 2 1 1
2 1 1 0
3 1 1 0
Need to do this in SAS. There is an example of this in Oracle but not in SAS.
If I understand correctly, this is a simple query using proc sql. For all the ids in the first table:
proc sql;
select id, count(val1) as val1, count(val2) as val2, count(val3 as val3)
from table1
group by id;
run;
count() counts the number of non-NULL values in a column or expression.

Merging of rows based on data

In my application I am using SQL Server. The output of one of the queries is:
Name countA countB countC countD countE countF
Name1 NULL NULL 1 NULL NULL NULL
Name2 NULL NULL 1 NULL NULL NULL
Name2 NULL NULL NULL NULL NULL 1
Name3 NULL NULL NULL NULL NULL 1
Name3 NULL NULL 6 NULL NULL NULL
I am expecting the output to be a single row representing the count data as is shown below.
Name countA countB countC countD countE countF
Name1 NULL NULL 1 NULL NULL NULL
Name2 NULL NULL 1 NULL NULL 1
Name3 NULL NULL 6 NULL NULL 1
What do I need to change to fix this query?
Looking at the data, you should just be able to apply a GROUP BY to the query based on Name, and apply a SUM aggregate to countA, countB, etc.

Select distinct not-null rows SQL server 2005

I ran into the following problem.
I have a table like this:
ID ID1 ID2 ID3 ID4 ID5
1 NULL NULL NULL NULL 1
2 NULL NULL NULL 2 NULL
3 NULL NULL NULL 2 1
4 3 NULL NULL 2 NULL
5 3 NULL NULL 2 1
6 NULL 5 NULL 2 NULL
And I need to get distinct rows it terms that NULL equals any value. For this example the answer is:
ID ID1 ID2 ID3 ID4 ID5
5 3 NULL NULL 2 1
6 NULL 5 NULL 2 NULL
P.S. Here ID is primary key hence unique. ID1-ID5 - any integers.
Thanks in advance!
UPDATED
Saying that null equals any number I mean that it's absorbed by any number.
This works, don't know if it can be made any simpler
SELECT ID1, ID2, ID3, ID4, ID5
FROM IDS OUTT
WHERE NOT EXISTS (SELECT 1
FROM IDS INN
WHERE OUTT.ID != INN.ID AND
(ISNULL(OUTT.ID1, INN.ID1) = INN.ID1 OR (INN.ID1 IS NULL AND OUTT.ID1 IS NULL)) AND
(ISNULL(OUTT.ID2, INN.ID2) = INN.ID2 OR (INN.ID2 IS NULL AND OUTT.ID2 IS NULL)) AND
(ISNULL(OUTT.ID3, INN.ID3) = INN.ID3 OR (INN.ID3 IS NULL AND OUTT.ID3 IS NULL)) AND
(ISNULL(OUTT.ID4, INN.ID4) = INN.ID4 OR (INN.ID4 IS NULL AND OUTT.ID4 IS NULL)) AND
(ISNULL(OUTT.ID5, INN.ID5) = INN.ID5 OR (INN.ID5 IS NULL AND OUTT.ID5 IS NULL)))
EDIT: Found a sweeter alternative, if your ids never have negative numbers
SELECT ID1, ID2, ID3, ID4, ID5
FROM IDS OUTT
WHERE NOT EXISTS (SELECT 1
FROM IDS INN
WHERE OUTT.ID != INN.ID AND
coalesce(OUTT.ID1, INN.ID1,-1) = isnull(INN.ID1,-1) AND
coalesce(OUTT.ID2, INN.ID2,-1) = isnull(INN.ID2,-1) AND
coalesce(OUTT.ID3, INN.ID3,-1) = isnull(INN.ID3,-1) AND
coalesce(OUTT.ID4, INN.ID4,-1) = isnull(INN.ID4,-1) AND
coalesce(OUTT.ID5, INN.ID5,-1) = isnull(INN.ID5,-1))
EDIT2: There is one case where it won't work - in case two rows (with different ids) have exact same form. I am assuming that it is not there. If such a thing is present, then first create a view with a select distinct on the base table first, and then apply this query.
Statement of your problem as I understand it:
You start with the full table:
ID ID1 ID2 ID3 ID4 ID5
1 NULL NULL NULL NULL 1
2 NULL NULL NULL 2 NULL
3 NULL NULL NULL 2 1
4 3 NULL NULL 2 NULL
5 3 NULL NULL 2 1
6 NULL 5 NULL 2 NULL
Then you eliminate "duplicate" rows, ie. rows that have less, but the same values as other rows (except NULL — and the ID column is not included):
Row 1 is eliminated because row 3 is identical, but has more values in the places where row 1 has NULL.
Row 2 likewise gets eliminated by (either of) row 2 or 4.
Row 3 and 4 are eliminated by row 5.
You're then left with rows 5 and 6:
ID ID1 ID2 ID3 ID4 ID5
5 3 NULL NULL 2 1
6 NULL 5 NULL 2 NULL
My answer:
Frankly, I don't see how this could be done with SQL's SELECT DISTINCT, or more generally, with SQL's set-based logic. I could imagine that you might be able to do this kind of filtering with a more procedural approach (e.g. with cursors) — but I can't provide a solution for this.
A note about terminology:
NULL equals any value
NULL never equals any value, because NULL is itself not a value; it is the absence of a value. NULL essentially means "unknown". (The fact that NULL is not a value is the reason why you shouldn't write IDx = NULL, but IDx IS NULL instead.)
If ID1, ID2 (...) has always the same value, as in your example, you could do it
Select
SUM(id1)/COUNT(id1),
SUM(id2)/COUNT(id2),
SUM(id3)/COUNT(id3),
SUM(id4)/COUNT(id4),
SUM(id5)/COUNT(id5) From TABLE
The functions SUM and COUNT will ignore that null values.
But still little confused your question.. :)