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
Related
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.
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.
This question already has answers here:
Selecting first row per group
(2 answers)
Closed 6 years ago.
I have the table named DealOffers :
I want to select only one record from each group of dealIds where
Price is minimum.
i.e : the expected output should be like this:
You can do something like this. However, you should consider performance if you end up having to do this on a massive scale.
select *
from (
select *,
SeqNum = row_number() over(
partition by DealId
order by Price)
from DealOffers) do
where do.SeqNum = 1;
This question already has answers here:
Oracle SQL - How to Retrieve highest 5 values of a column [duplicate]
(5 answers)
Oracle SELECT TOP 10 records [duplicate]
(6 answers)
Closed 6 years ago.
i have 2 tables .
abc(CID(pk), cname,)
order(order_id(pk), CID(fk), number_of_rentals)
i want to fetch top 10 customers based on number of rentals.
SELECT cid, sum(no_rentals) as sum
FROM orders
group by cid, no_rentals
order by no_rentals desc;
how can i use rownum function in above query to fetch the desired output
Just wrap your query in:
SELECT * FROM ( your_query ) WHERE ROWNUM <= 10;
However, your query does not look like it is going to do what you intend as the GROUP BY no_renalts will mean that each distinct no_rentals value will be in its own group and you will not sum the values for each customer so you probably don't want to include it in the GROUP BY. Also, if you want to order by the total number of rentals then you want to ORDER BY SUM( no_rentals ) (or by its alias) like this:
SELECT cid,
SUM(no_rentals) as total_no_rentals
FROM orders
GROUP BY cid
ORDER BY total_no_rentals DESC;
Then you can apply the row limit like this:
SELECT *
FROM (
SELECT cid,
SUM(no_rentals) as total_no_rentals
FROM orders
GROUP BY cid
ORDER BY total_no_rentals DESC
)
WHERE ROWNUM <= 10;
This question already has answers here:
How do I find duplicate values in a table in Oracle?
(13 answers)
Closed 7 years ago.
I am writing this query to find duplicate CTN Records in table1. So my thinking is if the CTN_NO appears more than twice or higher , I want it shown in my SELECT * statement output on top.
I tried the following sub-query logic but I need pulls
SELECT *
table1
WHERE S_IND='Y'
and CTN_NO = (select CTN_NO
from table1
where S_IND='Y'
and count(CTN_NO) < 2);
order by 2
Using:
SELECT t.ctn_no
FROM YOUR_TABLE t
GROUP BY t.ctn_no
HAVING COUNT(t.ctn_no) > 1
...will show you the ctn_no value(s) that have duplicates in your table. Adding criteria to the WHERE will allow you to further tune what duplicates there are:
SELECT t.ctn_no
FROM YOUR_TABLE t
WHERE t.s_ind = 'Y'
GROUP BY t.ctn_no
HAVING COUNT(t.ctn_no) > 1
If you want to see the other column values associated with the duplicate, you'll want to use a self join:
SELECT x.*
FROM YOUR_TABLE x
JOIN (SELECT t.ctn_no
FROM YOUR_TABLE t
GROUP BY t.ctn_no
HAVING COUNT(t.ctn_no) > 1) y ON y.ctn_no = x.ctn_no
Try this query.. It uses the Analytic function SUM:
SELECT * FROM
(
SELECT SUM(1) OVER(PARTITION BY ctn_no) cnt, A.*
FROM table1 a
WHERE s_ind ='Y'
)
WHERE cnt > 2
Am not sure why you are identifying a record as a duplicate if the ctn_no repeats more than 2 times. FOr me it repeats more than once it is a duplicate. In this case change the las part of the query to WHERE cnt > 1