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.
Related
I would like to get a new ID, no matter the format (in the example below 11,12,13...)
Based on the following condition:
Every time the days column value is greater then 1 and not null then current row and all following ones will get the same ID until a new value will meet the condition.
Within the same email
Below you can see the expected 1 (in the format of XX)
I thought about using two conditions with the following order between them
Every time the days column value is greater then 1 then all following rows will get the same ID until a new value will meet the condition.
2.AND When lag (previous) is equal to 0/1/null.
Assuming you have an EmailDate column over which you're ordering (a DATETIME field, really), try something like this:
WITH
TableNameWithEmailDateIDs AS (
SELECT
*,
ROW_NUMBER() OVER (
ORDER BY
Email DESC,
EmailDate
) AS EmailDateID
FROM
TableName
),
IDs AS (
SELECT
*,
LEAD(EmailDateID, 1) OVER (
ORDER BY
Email,
EmailDate
) AS LeadEmailDateID
FROM
(
SELECT
*,
-- REMOVE +10 if you don't want 11 to be starting ID
ROW_NUMBER() OVER (
ORDER BY
Email DESC,
EmailDate
)+10 AS ID
FROM
TableNameWithEmailDateIDs
WHERE
Days > 1
OR Days IS NULL
) X
)
SELECT
COALESCE(TableName.EmailDate, IDs.EmailDate) AS EmailDate,
IDs.Email,
COALESCE(TableName.Days, IDs.Days) AS Days,
IDs.ID
FROM
IDs
LEFT JOIN TableNameWithEmailDateIDs TableName
ON IDs.Email = TableName.Email
AND TableName.EmailDateID BETWEEN
IDs.EmailDateID
AND IDs.LeadEmailDateID-1
ORDER BY
ID DESC,
TableName.EmailDate DESC
;
First, create a CTE that generates IDs for each distinct Email/Date combo (helpful for LEFT JOIN condition later). Then, create a CTE that generates IDs for rows that meet your condition (i.e. the important rows). Finally, LEFT JOIN your main table onto that CTE to fill in the "gaps", so to speak.
I suggest running each of the components of this query independently to fully understand what's going on.
Hope it helps!
This question already has answers here:
How to get the top 10 values in postgresql?
(4 answers)
Closed 7 months ago.
i am using postgresql. i want to be able to select or delete the first n rows after sorting the ascendingly according to the timestamp of insertion.
i found an example but it uses a table named logtable, i do not have that logtable.
in otherwords, i want to sort the records in the table based on the time of data insertion into the table then selected the first N rows
please let me know how to achieve this task
You could use ROW_NUMBER:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY ts_insertion) rn
FROM yourTable
)
SELECT *
FROM cte
WHERE rn <= N -- replace N with your actual limit value
ORDER BY ts_insertion;
If you only want the first n rows, you can use LIMIT n, a window function is not necessary.
You can also use OFFSET:
SELECT column1, column2
FROM table_name
ORDER BY column1 ASC
LIMIT row_count OFFSET row_to_skip;
This question already has answers here:
How to delete duplicate rows in SQL Server?
(26 answers)
Closed 6 years ago.
I have a table with 82,535 rows, where 65,087 rows are unique by ID. When I pull the entire result set of 82,535 and copy to Excel and remove duplicates, it shows that there are 17,448 duplicates. But when I'm using the query below I'm getting different results:
SELECT
BLD_ID, COUNT(BLD_ID) AS [BLD_ID COUNT]
FROM
Project.BreakageAnalysisOutcome_SentToAIM
GROUP BY
BLD_ID
HAVING
COUNT(BLD_ID) > = 2
This query returns a value of 17,364
I know for sure that the number of unique BLD_ID is 65,087
Most likely reason fro that is duplicate record may have more than 2 occurrence.
find duplicate count
Select COUNT(BLD_ID)- COUNT( DISTINCT BLD_ID)
From Project.BreakageAnalysisOutcome_SentToAIM
Use CTE with a Row_Number Function instead of count with group by clause and filer by Row_Number > 1.
;WITH cte
AS
(
SELECT ID,
ROW_NUMBER() OVER(PARTITION BY ID ORDER BY ID) AS Rn
FROM [Table1]
)
DELETE cte WHERE Rn > 1
I have a table of 6 currency conversions, it's updated almost daily. Unfortunately the way the software works is it inserts new rows rather than updating the existing ones. My previous SELECT was as follows
SELECT FROM_CURRENCY_ID, XCHG_RATE
FROM
(
SELECT TOP 6 FROM_CURRENCY_ID, XCHG_RATE
FROM SHARED_CURRENCY_EXCHANGE
WHERE NOT FROM_CURRENCY_ID = 'CAD'
ORDER BY RECORD_CREATED desc
) t
ORDER BY FROM_CURRENCY_ID
The issue now is some records got updated while others didn't so my query returns duplicate values for one of the currencys and nothing for one. I need it to output the 6 unique FROM_CURRENCY_IDs and their XCHG_RATE with the newest RECORD_CREATED dates
I've been trying a group by to exclude the duplicate rows with no luck.
with x as
(select row_number() over(partition by from_currency_id order by record_created desc) rn, * from shared_currency_exchange)
select from_currency_id, xchg_rate from x
where rn = 1
This gives the most recent record a rownumber 1 and you can use the cte with this condition.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to select the nth row in a SQL database table?
I have a table that I want to select Select 1 record and in other command I want to select second row and in other command 3th row and ... how can I select for example 4th record from top of table without having the row number . just I want to select 4th row from top of table . how can I do this ?
you can select the 4th row by this code in MS sql server.
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY DayRangeId ASC) AS rownumber,
DayRangeId
FROM DayRangeTable
) as temptablename
WHERE rownumber = 4
You want the first row, then the second row, then the third row and then the fourth row?
Can't you select the top n rows, and itterate through them?
I'm not sure what you mean by without having the row number though. Do you mean "Select the 4th row without knowing I need the 4th row"???
If you really need a piece of SQL that can select a specific row...
;WITH
sequenced_data AS (
SELECT ROW_NUMBER() OVER (ORDER BY <whatever fields>) AS row_id, * FROM myTable
)
SELECT
TOP 1 *
FROM
sequenced_data
WHERE
row_id = #n