I have a query which produces several results. I have concatenated several columns into 1 as an ID. I only want to show the rows where the ID is unique.
The below image is an example of my table:
As you can see the ID is repeated a few times. How can I construct a query to show only the 3 unique rows?
Nesting this query and using distinct(RowID) shows the three rows but I cannot show the rest of the columns?
Any ideas welcome. Thank you!
Use distinct in the select for all columns
Query:
select distinct RowID, OrderNum, cDescription, Thickness, UllTimberThickness, Width, UllTimberWidth, Length
from YourTable
Use GROUP BY:
SELECT RowID, OrderNum, cDescription, Thickness, etcetera ...
FROM dbo.TableName
GROUP BY RowID, OrderNum, cDescription, Thickness, etcetera ...
( etcetera is a placeholder for the rest of your columns )
Try this:
SELECT *
FROM mytable t1
WHERE
(SELECT COUNT(*) FROM mytable t2
where t2.id = t1.id) = 1
In this way, you get all rows where id is unique. I write this query because I don't know if at your ID other fields are the same, because you have built your field with a set of information. If all the columns are the same for equal id so you can use the statement DISTINCT as adviced you by Vasanth Sundaralingam in his post.
I'm a little confused by what "get the three unique rows means".
If you mean rows that are unique, use count(*) as a window function:
select *
from (select t.*,
count(*) over (partition by id) as cnt
from t
) t
where cnt = 1;
If you mean one example of each row, use row_number():
select *
from (select t.*,
row_number(*) over (partition by id order by (select NULL)) as seqnum
from t
) t
where seqnum = 1;
Related
I am trying to group by a column. The problem is that the NULL values of the column are grouped as a separate group.
I want the NULL values to be added to each of the other group values instead.
Example of a table:
The results I want to get from group by with sum aggregation over the 'val' column:
Can anyone help me?
Thanks!
You can precalculate the value to spread through the rows and then just do arithmetic:
select t.id,
sum(t.val) + (null_sum / cnt_id)
from t cross join
(select count(distinct id) as cnt_id,
sum(case when id is null then val else 0 end) as null_sum
from t
) tt
group by t.id;
Note some databases do integer division, so you might need null_sum * 1.0 / cnt_id.
A GROUP BY operation can't really generate values for each group on the fly, so logically you need records which are missing to really be present.
One approach is to use a calendar table to generate a table containing one NULL record for each id group:
WITH ids AS (
SELECT DISTINCT id FROM yourTable
WHERE id IS NOT NULL
),
cte AS (
SELECT t1.id, t2.val
FROM ids t1
CROSS JOIN yourTable t2
WHERE t2.id IS NULL
)
SELECT t.id, SUM(t.val) AS val
FROM
(
SELECT id, val FROM yourTable WHERE id IS NOT NULL
UNION ALL
SELECT id, val FROM cte
) t
GROUP BY
id;
Demo
I have the following table (must shorter version than the real one),
and I want to all the rows with max _ values for each _ displayed.
How should I do this?
Table Now
Table I want to have
thanks a lot in advance!!
Using the dense_rank function and a derived table would be appropriate for this (please note I used underscores instead of spaces in the column names):
select group_type
,desk_number
,comments
from
(select *
,dense_rank() over(partition by group_type order by desk_number desc) dr
from mytable) t1
where t1.dr = 1
I made a rextester sample that you can try here
Let me know if you have any questions.
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
This answers your question quite well but I will convert it for your convenience <3
SELECT *
FROM table
INNER JOIN
(SELECT comments, MAX([desk number]) AS MaxDesk
FROM table
GROUP BY comments) groupedtable
ON table.[desk number]= groupedtable.[desk number]
AND table.comments= groupedtable.MaxDesk
try this :
WITH CTE
AS
(
SELECT
SeqNo = ROW_NUMBER() OVER(ORDER BY CAST(DeskNumber AS INT) DESC PARTITION BY GroupType),
GroupType,
DeskNumber,
[Comment]
FROM YourTable
)
SELECT
*
FROM CTE WHERE CTE.SeqNo = 1
I have a table t1 with two int fields(id,month) and I have populated it with some values.
What I would like to see as an output is, the maximum of (count of id in a month). I have tried the following code and it works fine:
select id,max(freq) as maxfreq from
(select id,month,count(*) as freq
from t1
group by id,month) a
group by id
order by maxfreq desc
The result is:
ID MAXFREQ
1 3
2 3
3 1
4 1
This is fine. How to achieve this using the over partition by clause? And which one is more efficient? In reality my table consists of several thousands of records. So doing a subquery wont be a good idea I guess! Thanks for any help. Here's the fiddle
;WITH tmp AS (select id, row_number() over (partition by id, month order by id) rn
FROM t1)
SELECT t.id, max(tmp.rn) as maxfreq
from t1 t
INNER JOIN tmp ON tmp.id = t.id
GROUP BY t.id
You can try this -
select id,max(freq) as maxfreq from
(select id,row_number() over (partition by id,month ORDER BY id) as freq
from t1
) a
group by id
order by id,maxfreq desc
but from a performance standpoint, I do not see much difference between your original query and this one.
Same solution but with using CTE.
Actually there is no point to forcibly use windowing functions to this issue.
Compare both solutions with plan explorer.
;with c1 as
( select id,month,count(*) as freq
from t1
group by id,month
)
select id, max(freq) as maxfreq
from c1
group by id
order by maxfreq desc;
Struggling with what's probably a very simple problem. I have a query like this:
;WITH rankedData
AS ( -- a big, complex subquery)
SELECT UserId,
AttributeId,
ItemId
FROM rankedData
WHERE rank = 1
ORDER BY datEventDate DESC
The sub-query is designed to grab a big chunk of interlined data and rank it by itemId and date, so that the rank=1 in the above query ensures we only get unique ItemIds, ordered by date. The partition is:
Rank() OVER (partition BY ItemId ORDER BY datEventDate DESC) AS rk
The problem is that what I want is the top 75 records for each UserID, ordered by date. Seeing as I've already got a rank inside my sub-query to sort out item duplicates by date, I can't see a straightforward way of doing this.
Cheers,
Matt
I think your query should look like
SELECT t.UserId, t.AttributeId, t.ItemId
FROM (
SELECT UserId, AttributeId, ItemId, rowid = ROW_NUMBER() OVER (
PARTITION BY UserId ORDER BY datEventDate
)
FROM rankedData
) t
WHERE t.rowid <= 75
I would like to create a select query statement with autonumber.. like..
select * from tbl1
will give me everything from table.
The result I'd like to get is..
1 data
2 data
3 data
So how can I do to get that number..??
like..
select (for autonumber), * from tbl1
the data in my table will repeated (no unique data)
Use ROW_NUMBER:
SELECT ROW_NUMBER() OVER (ORDER BY col1) AS rn, * FROM tbl1
To filter the results based on the row number use this:
SELECT * FROM
(
SELECT ROW_NUMBER() OVER (ORDER BY col1) AS rn, * FROM tbl1
) T1
WHERE rn = 5
You may need to find the identity's offset e.g. last ID of second table:
DECLARE #lastAutoID int
SET #lastAutoID = abs(( Select max(convert(float,[ConsID]))
FROM [RXPIPEDB]...[consumption] ) )
Then use ROW_NUMBER():
#lastAutoID + ROW_NUMBER() OVER (ORDER BY oldICN_str)