Select top entry per ID from data table - SQL - sql

Assuming I have the following data table:
ID VALUE
--- -------
123 a
123 b
456 c
456 d
789 e
How can I get the output to only select the top entry per ID, assuming the data is already ordered. Ie, I need the data to show:
ID VALUE
--- -------
123 a
456 c
789 e

SQL tables represent unordered sets. There is no ordering to the table, unless you have a column that specifies the ordering.
This is fundamental in SQL. Let me assume you have an ordering column. Then you can do:
select t.*
from t
where t.ordcol = (select max(t2.ordcol) from t t2 where t2.id = t.id);

Also you can add the ordering dynamically,
e.g.
select * from
(select id, value, dense_rank() OVER (ORDER BY value asc) as myrank from #mytable ) aa
where myrank=1

Related

How can I add a column with its values from one table into another table in SQL?

I know this question has been probably asked a million times, but I can't seem to find what I do.
I have this table called Customer that only has 1 attribute (id)
id
----
1
2
3
4
5
And I have another table called Names that also has one attribute (name)
name
----
Tom
Bob
Sam
Angel
Joe
I want to add the column name from table Names to the table Customer so it turns out like this
id | name
------------
1 Tom
2 Bob
3 Sam
4 Angel
5 Joe
How can I do this in sql?
You could do this:
alter table customer add column name nvarchar(255);
with toupdate (
select c.*, row_number() over (order by (select null)) as seqnum
from customer c
)
update toupdate
from (select n.*, row_number() over (order by select null) as seqnum
from names n
) n
where toupdate.seqnum = n.seqnum;
Note that the order of the match is not guaranteed. SQL tables represent unordered sets. There is no "default" ordering with a column specifying the ordering. And in one column tables, you don't have such a column.

Updating Data having same id but different Data in Row

I have a record with same ID but different data in both rows
While updating the final result should be the last record of that ID present in data.
Example
ID | Name | PermanentAddrss | CurrentLocation
1 | R1 | INDIA | USA
1 | R1 | INDIA | UK
Now for ID 1 the record which will be loaded in database
1|R1|INDIA|UK
How this can be done in SQL server for multiple records?
Please understand that SQL server does not store or fetch data in order of data insertion, so to find the latest/last record you should have some way to order the records.
This is typically a timestamp column like last_modified_date. Your current table is prime candidate for a slow changing dimension type 2; and you should consider implementing it.
See explanation on Kimball's group site.
If you are really not affected by any order and just need a row for each id you can try below query.
select
ID,
Name,
PermanentAddress,
CurrentLocation
from
(select
*,
row_number() over(partition by id order by (select null)) r
from yourtable)t
where r=1
You can identify the latest ID value by:
SELECT B.ID, A.NAME, A.PERMANENTADDRS, A.CURRENTLOCATION
FROM
(SELECT ID, NAME, PERMANENTADDRS, CURRENTLOCATION, MAX(RNUM) AS LATEST_ID FROM
(SELECT ID, NAME, PERMANENTADDRS, CURRENTLOCATION, ROW_NUMBER() OVER (PARTITION BY ID) AS RNUM FROM YOUR_TABLE)
GROUP BY ID, NAME, PERMANENTADDRS, CURRENTLOCATION) A
INNER JOIN
YOUR_TABLE B
ON A.LATEST_ID = B.ID;
This will take the last populated record for a given ID value. If the logic for latest record is different, it can be appropriately incorporated in the query.

displaying distinct column value with corresponding column random 3 values

I have a table employee with columns (state_cd,emp_id,emp_name,ai_cd) how can i display disticnt state_cd with 3 different values from ai_cd
the answer should be
state_cd ai_cd
------- --------
TX 1
2
5
CA 9
10
11
This type of operation is normally better done in the application. But, you can do it in the query, if you really want to:
select (case when row_number() over (partition by state_cd order by ai_cd) = 1
then state_cd
end) as state_cd,
ai_cd
from employee e
order by e.state_cd, e.ai_cd;
The order by is very important, because SQL result sets are unordered. Your result requires ordering in order to make sense.
Just group by state_id and then count using count(Distinct column_name_)
select state_id from (select state_id,COUNT(DISTINCT ai_cd) as cnt from employee group by state_id) where cnt==3

Selecting distinct values from table using two columns

I have following data in the table.
Id Name
1 Abc
2 Abc
3 Xyz
4 Xyz
5 def
6 def
I want following results from the query
Id Name
1 Abc
2 Xyz
3 def
I want to avoid duplicates in the name column.
Any help is greatly appreciated.
Select distinct
id, name
from table A
will not work as ids are having a different values.
Use a group by instead.
select
min(id), [name]
from
tableA
group by [name]
Note that in your example, the ids that corresponds with Xyz are 3 and 4, so getting a 2 next to Xyz is only possible if you break the integrity of the table. If you are just looking for an auto number next to the ids you can do this:
SELECT row_number() OVER (ORDER BY min(id)) id,
name
FROM tableA
group by name
You can get your specific result using:
select row_number() over (order by min(id)) as id, name
from table A
group by name;
Renumbering the rows seems strange, but row_number() will do that.

Select particular not grouped column from grouped set

The topic might be a little bit unclear but I couldn't describe in a single sentence what I want to achieve.
Say I have a table that is (columns)
id INT PK
name VARCHAR
date DATE
I have a grouping select
select
name,
max(date)
from table
group by name
that gives me a name and the latest date.
What is the easiest way to join the id column to the current aggregated result set with the id value where the date was the maximum?
Let me explain what my goal is with an example:
The table is filled with the data as follows
id name date
1 david 2012-12-12
2 david 2013-12-02
3 patrick 2014-01-02
4 patrick 2012-11-11
and by my query I'd like to get the following result
id name date
2 david 2013-12-02
3 patrick 2014-01-02
Notice that all the records for name = 'david' are aggregated and the maximum date is selected. How to get the row id for this maximum date?
One option is to use ROW_NUMBER():
SELECT id, name, date
FROM (
SELECT id, name, date,
row_number() over (partition by name order by date desc) rn
FROM yourtable
) t
WHERE rn = 1
SQL Fiddle Demo
Another option is to join the table back to itself using the MAX() aggregate. This option could potentially result in ties if multiple id/name combinations share the same max date:
SELECT t.id, t.name, t.date
FROM yourtable t
JOIN (SELECT name, max(date) maxdate
FROM yourtable
GROUP BY name) t2 on t.name = t2.name AND t.date = t2.maxdate
More Fiddle