Distinct one field but wanted to display all the columns [duplicate] - sql

This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 3 years ago.
Anyone can help me the easiest way to distinct one particular field/column but displaying all fields/columns? Please see attached image the data-source, I've tried to query on my own but it displays all the 16 records I'm looking for 6 records only.
USE DBASE;
WITH t1 as (SELECT DISTINCT STATE
FROM DSOURCE),
t2 as (SELECT *
FROM DSOURCE)
SELECT
*
FROM
t1
LEFT JOIN t2 ON t1.STATE=t2.STATE

You want row_number() :
select d.*
from (select d.*, row_number() over (partition by d.state order by d.f) as seq
from dsource d
) d
where d.seq = 1;

row_number() is your saviour here:
;WITH CTE AS
(
SELECT *, ROW_NUMBER() OVER(PARTITION BY STATE ORDER BY B,C,D,E,F) Corr
FROM dsource
)
SELECT *
FROM CTE
WHERE Corr = 1

You clearly want the first row from each `state's data. However, your dataset doesn't have a clear indicator of what is "first". So, you need to take one of two approaches.
If your data actually has an IDENTITY column, you can approach it with a query like this:
SELECT *
FROM DSOURCE d
WHERE ID In (
SELECT MIN(ID)
FROM DSOURCE ds
GROUP BY State
)
If not, you will need to use the row_number() functionality as shown above. #yogesh-sharma has the best example of using the this.

Related

Using TOP and WHERE in SQL [duplicate]

This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 3 months ago.
Is there a way to use TOP and WHERE multiple times? similar as a for loop to create a table?
I am using the following query to create a table that contains the top 26 records where the value of the column [code] is 11:
SELECT TOP 26 [date]
,[group]
,[code]
,[pol]
,[relation]
FROM [database].[table1] WHERE group in ('A','B','C',...,'Z') and code = '11'
The problem with this query is that I get 26 records with the value of the column [group] equal to A. This happens because there are thousands of records that meet that criterion.
Ideally, I would like the top 1 of each group (A to Z) with the value of code 11. I could achieve that by running the query above 26 times using TOP 1 and a different value of group, but this is impractical.
Is there any way to run this query multiple times to get the desired table?
Thanks in advance!
You can use a CTE to assign a ROW_NUMBER(), then only return rows WHERE ROW_NUMBER() = 1. You may need to adjust the PARTITION/ORDER BY depending on your data and what you're expecting your result set to be.
;WITH cte AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY [group], code ORDER BY code ASC) AS rn
FROM table1
)
SELECT *
FROM cte
WHERE rn = 1 AND code = 11
Demo here.
Assuming that your database support WITH TIES, then no need for a subquery. You can just order by with row_number:
SELECT TOP 1 WITH TIES
[date]
,[group]
,[code]
,[pol]
,[relation]
FROM [database].[table1]
WHERE group in ('A','B','C',...,'Z') and code = '11'
ORDER BY ROW_NUMBER() OVER(PARTITION BY [group] ORDER BY [date] desc)
You did not tell which column should be used to identify the top row per group, so I used a descending sort on the date. For each group, ROW_NUMBER assigns 1 to the row with the latest date ; TOP 1 WITH TIES then selects all such rows.

SQL filter query result [duplicate]

This question already has answers here:
Get top 1 row of each group
(19 answers)
Closed 9 months ago.
I have a problem to create query.
Now I have query like this:
SELECT DISTINCT sad.item_id, sad.attrb_code, sad.sub_item_id, sad.attrb_type, sad.description, sad.effective_date, sad.creation_date, sad.last_update_datetime, sad.last_user_id
FROM table1 AS sad
WHERE NOT EXISTS
(
SELECT 1 FROM table2 AS saa
WHERE sad.attrb_code = saa.attrb_code AND sad.item_id = saa.item_id AND saa.attrb_flag = 'N'
)
AND sad.attrb_code IN ('VOICE', 'SMS2D', 'MMS2D', 'TRANS' )
AND sad.item_id = '???' ;
and result looks like this:
Now I would like to filter results, to select only the newest one (by effective_date) for every unique attrb_code. So I would like to achive something like this:
Wrap your query in a CTE for clarity, then top 1 with ties and row_number:
;with original as
(
<put your entire query here>
)
select top 1 with ties *
from original
order by row_number() over (partition by attrb_code order by effective_date desc) asc

Selecting TOP 1 Columns where duplicate exists and selecting all where no duplicate exists

Given the list of Names, Accounts and Positions I am trying to:
Select the 1st position where there are more than 1 records with the same Name and Account
If there is only 1 record with the Name and Account, then select details.
My current query looks like the following:
SELECT *
FROM CTE cte1
JOIN
(
SELECT Name, OppName FROM CTE GROUP BY Name, OppName HAVING COUNT(Name)>1
) as cte2
on cte2.Name = cte1.Name and cte2.OppName = cte1.OppName
ORDER BY cte1.OppName, cte1.Name
I have not posted the rest of the CTE query as it is way to long.
However, this is only providing me with the results where the Name and Accounts are the same and the Positions are different.
I.E. If Oera worked at Christie's as a Sales Analyst and a Developer It would only Select the record where Oera worked at Christie's as a Developer.
How do I modify this query accordingly?
Are you looking for something like this?
SELECT *
FROM CTE AS cte1
JOIN
(
SELECT Name, OppName,COUNT(Name) PARTITION BY (Name,OppName) cnt
FROM CTE
) AS cte2
ON cte2.Name = cte1.Name and cte2.OppName = cte1.OppName
WHERE cnt > 1
ORDER BY cte1.OppName, cte1.Name

Distinct on three columns in sql server 2008

I have a 20 Columns Table which have duplicate value but not in all columns. that what normal distinct clause not working on it..
so i want to apply distinct on three columns (name,fname,dob) , but how? . Please give me any solution .
You could use ROW_NUMBER with a common-table-expression(CTE):
WITH CTE AS
(
SELECT t.*, RN = ROW_NUMBER() OVER (PARTITION BY name,fname,dob ORDER BY name,fname,dob)
FROM dbo.TableName t
)
SELECT * FROM CTE WHERE RN = 1
This takes one per group. Change ORDER BY name,fname,dob according to your logic.

SQL query to select distinct row with minimum value

I want an SQL statement to get the row with a minimum value.
Consider this table:
id game point
1 x 5
1 z 4
2 y 6
3 x 2
3 y 5
3 z 8
How do I select the ids that have the minimum value in the point column, grouped by game? Like the following:
id game point
1 z 4
2 y 5
3 x 2
Use:
SELECT tbl.*
FROM TableName tbl
INNER JOIN
(
SELECT Id, MIN(Point) MinPoint
FROM TableName
GROUP BY Id
) tbl1
ON tbl1.id = tbl.id
WHERE tbl1.MinPoint = tbl.Point
This is another way of doing the same thing, which would allow you to do interesting things like select the top 5 winning games, etc.
SELECT *
FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY ID ORDER BY Point) as RowNum, *
FROM Table
) X
WHERE RowNum = 1
You can now correctly get the actual row that was identified as the one with the lowest score and you can modify the ordering function to use multiple criteria, such as "Show me the earliest game which had the smallest score", etc.
This will work
select * from table
where (id,point) IN (select id,min(point) from table group by id);
As this is tagged with sql only, the following is using ANSI SQL and a window function:
select id, game, point
from (
select id, game, point,
row_number() over (partition by game order by point) as rn
from games
) t
where rn = 1;
Ken Clark's answer didn't work in my case. It might not work in yours either. If not, try this:
SELECT *
from table T
INNER JOIN
(
select id, MIN(point) MinPoint
from table T
group by AccountId
) NewT on T.id = NewT.id and T.point = NewT.MinPoint
ORDER BY game desc
SELECT DISTINCT
FIRST_VALUE(ID) OVER (Partition by Game ORDER BY Point) AS ID,
Game,
FIRST_VALUE(Point) OVER (Partition by Game ORDER BY Point) AS Point
FROM #T
SELECT * from room
INNER JOIN
(
select DISTINCT hotelNo, MIN(price) MinPrice
from room
Group by hotelNo
) NewT
on room.hotelNo = NewT.hotelNo and room.price = NewT.MinPrice;
This alternative approach uses SQL Server's OUTER APPLY clause. This way, it
creates the distinct list of games, and
fetches and outputs the record with the lowest point number for that game.
The OUTER APPLY clause can be imagined as a LEFT JOIN, but with the advantage that you can use values of the main query as parameters in the subquery (here: game).
SELECT colMinPointID
FROM (
SELECT game
FROM table
GROUP BY game
) As rstOuter
OUTER APPLY (
SELECT TOP 1 id As colMinPointID
FROM table As rstInner
WHERE rstInner.game = rstOuter.game
ORDER BY points
) AS rstMinPoints
This is portable - at least between ORACLE and PostgreSQL:
select t.* from table t
where not exists(select 1 from table ti where ti.attr > t.attr);
Most of the answers use an inner query. I am wondering why the following isn't suggested.
select
*
from
table
order by
point
fetch next 1 row only // ... or the appropriate syntax for the particular DB
This query is very simple to write with JPAQueryFactory (a Java Query DSL class).
return new JPAQueryFactory(manager).
selectFrom(QTable.table).
setLockMode(LockModeType.OPTIMISTIC).
orderBy(QTable.table.point.asc()).
fetchFirst();
Try:
select id, game, min(point) from t
group by id