Combine Row Values to "Others" - sql

I have a maybe really tricky question. I have a table with costs, very simple:
Cost name, cost value
And I want to output the TOP 10 costs values with the name, which is no problem, BUT: as 11th row, I want to output all others sum as "Others" marked ... Is that possible with a SQL query?
I hope you understand my question and I'm very thankful for all helpful answers.
Best regards,
Tobias
UPDATE:
<< Data Example >>

Please try:
;with T as(
select *, ROW_NUMBER() over (order by value desc) RNum
from YourTable
)
select value, name from T
where RNum<=10
union all
select sum(value), 'Others'
from T
where RNum>10

Perhaps something like this?
select * from (select top (10) name, value from costs order by value) s1
UNION (
select 'other', sum(value) from costs
where name not in (select top 10 Name from costs order by value)
)
This assumes Name is a PK on costs.

;with CTE as(SELECT Name ,
value ,row_number() OVER (ORDER BY Name) AS RowNumber FROM #Temp )
select Name,value
from cte
Where RowNumber<11
union
select 'Other',Sum(value)
from cte
Where RowNumber>=11
Sample Fiddle

Related

Is there any optimised way in sql sever to optimse this code, I am trying to find 2nd duplicate

Is there any optimised way in sql sever to optimse this code, I am trying to find 2nd duplicate
WITH CTE AS (
SELECT *,
ROW_NUMBER() OVER(PARTITION BY id,AN_KEY ORDER BY [ENTITYID]) AS [rn]
FROM [data].[dbo].[TRANSFER]
)
select *
INTO dbo.#UpSingle
from CTE
where RN=2
UPDATE:
As GurV pointed out - this query doesn't solve the problem. It will only give you the items that have exactly two duplicates, but not the row where the second duplicate lies.
I am just going to leave this here from reference purposes.
Original Answer
Why not try something like this from another SO post: Finding duplicate values in a SQL table
SELECT
id, AN_KEY, COUNT(*)
FROM
[data].[dbo].[TRANSFER]
GROUP BY
id, AN_KEY
HAVING
COUNT(*) = 2
I gather from your original SQL that the cols you would want to group by on are :
Id
AN_KEY
Here is another way to get the the second duplicate row (in the order of increasing ENTITYID of course):
select *
from [data].[dbo].[TRANSFER] a
where [ENTITYID] = (
select min([ENTITYID])
from [data].[dbo].[TRANSFER] b
where [ENTITYID] > (
select min([ENTITYID])
from [data].[dbo].[TRANSFER] c
where b.id = c.id
and b.an_key = c.an_key
)
and a.id = b.id
and a.an_key = b.an_key
)
Provided there is an index on id, an_key and ENTITYID columns, performance of both your query and this should be acceptable.
Let me assume that this query does what you want:
WITH CTE AS (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY id, AN_KEY
ORDER BY [ENTITYID]) AS [rn]
FROM [data].[dbo].[TRANSFER] t
)
SELECT *
INTO dbo.#UpSingle
FROM CTE
WHERE RN = 2;
For performance, you want a composite index on [data].[dbo].[TRANSFER](id, AN_KEY, ENTITYID).

Select Top 100 Groups

I have thousands of groups in a table, something like :
1..
1..
2..
2..
2..
2..
3..
3..
.
.
.
10000..
10000..
How can i make a select that give me the Top 3 groups each time.
I Want something like select Top 3 from rows , but it have to return the first three groups not the first three rows.
You can try this :
;with cte as (
select distinct groupId from mytable order by groupid
)
select * from mytable where TheGroupId in (select top 3 groupdid from cte)
You can use DENSE_RANK to assign a number to each group. All members of the same group will have the same number. Then in an outer query, select top 3 groups:
SELECT *
FROM (SELECT *, DENSE_RANK() OVER (ORDER BY id) AS rnk
FROM mytable ) t
WHERE t.rnk <= 3
The above query assumes that id is the column used to group records together.
SQL Fiddle Demo
Use Ranking function Row_Number() :
SELECT *
FROM (SELECT *,
Row_number()
OVER(
partition BY GroupId
ORDER BY GroupId) AS [rn]
FROM YourTable) t
WHERE rn <= 3
Check this MSDN doc for details of all ranking functions.
There is a sql TOP statement that does this
SELECT TOP number|percent column_name(s) FROM table_name;
a description of what it does and how it is used in alternative sql statements for example for mysql and ms access can be found here: http://www.w3schools.com/sql/sql_top.asp
My bad i misread your question, this will return the top rows not groups, could you explain what you are trying to do in more detail?
SELECT *
FROM
(SELECT *
,ROW_NUMBER() OVER (PARTITION BY [Group] ORDER BY [Group] ASC)rn
FROM TableName
)A
WHERE rn <= 3

Suming up Rows Based On Repetition Of Another Column

I Don't Know Why My Previous Topic Was Marked!!!???
This Is What I've Done So Far. I Can't Think Of Anything Else.
So Many Things I've Done To Reach To This Point Which Is Illustrated In My Problem Section. Which For Simplification I Made Name A,B,C,... .I'm Not Giving You My Homework.
My Problem:
Here is a SQL for SqlServer 2008 to solve your problem.
with data as (select name, count(*) as occurrence, sum(value) as sumvalue from mytab group by name)
select * from data where
occurrence=(select max(occurrence) from data)
and sumvalue=(select max(sumvalue) from data data2 where data2.occurrence=data.occurrence)
In data the needed values are collected (sum and count). Now we select the rows with max occurrence and filtering out the rows with the max value.
http://sqlfiddle.com/#!3/56b00/4
SELECT [Name], [Value]
FROM (
SELECT *, RANK() OVER(ORDER BY [Count] DESC, Value DESC) [rn]
FROM (
SELECT [Name], SUM(Value) [Value], COUNT(1) [Count]
FROM MyTable
GROUP BY Name
) t
) t
WHERE rn = 1
SQL Fiddle
or more simply
SELECT TOP 1 WITH TIES [Name], [Value]
FROM (
SELECT [Name], SUM(Value) [Value], COUNT(1) [Count]
FROM MyTable
GROUP BY Name
) t
ORDER BY [Count] DESC, Value DESC
SQL Fiddle

Select the first instance of a record

I have a table, myTable that has two fields in it ID and patientID. The same patientID can be in the table more than once with a different ID. How can I make sure that I get only ONE instance of every patientID.?
EDIT: I know this isn't perfect design, but I need to get some info out of the database and today and then fix it later.
You could use a CTE with ROW_NUMBER function:
WITH CTE AS(
SELECT myTable.*
, RN = ROW_NUMBER()OVER(PARTITION BY patientID ORDER BY ID)
FROM myTable
)
SELECT * FROM CTE
WHERE RN = 1
It sounds like you're looking for DISTINCT:
SELECT DISTINCT patientID FROM myTable
you can get the same "effect" with GROUP BY:
SELECT patientID FROM myTable GROUP BY patientID
The simple way would be to add LIMIT 1 to the end of your query. This will ensure only a single row is returned in the result set.
WITH CTE AS
(
SELECT tableName.*,ROW_NUMBER() OVER(PARTITION BY patientID ORDER BY patientID) As 'Position' FROM tableName
)
SELECT * FROM CTE
WHERE
Position = 1

Getting the smaller index for each duplicate in SQL

Let's say I have a table with two columns, one column for the ID and another for a Name. All the names in this table appear more than once.
How can I get all the IDs in the table excluding the smallest IDs for each Name?
In SQL Server 2005+ you could go like this:
SELECT ID FROM atable
EXCEPT
SELECT MIN(ID) FROM atable GROUP BY Name
I would use a CTE (Common Table Expression) using the ROW_NUMBER() ranking function for that:
;WITH GroupedNames AS
(
SELECT ID, Name,
ROW_NUMBER() OVER(PARTITION BY Name ORDER BY ID) AS 'RowNum'
FROM
dbo.YourTable
)
SELECT *
FROM GroupedNames
This will "partition" your data by means, e.g. create groups by name, and each group will get consecutive numbers starting at 1. This way, you can easily select everything except the entry (ID, Name) with the smallest ID with this:
.....
SELECT *
FROM GroupedNames
WHERE RowNum > 1
and if you need to, you can even use this construct to actually delete all those names with a row number bigger than 1 (all the "duplicates"):
;WITH GroupedNames AS
(
SELECT ID, Name,
ROW_NUMBER() OVER(PARTITION BY Name ORDER BY ID) AS 'RowNum'
FROM
dbo.YourTable
)
DELETE FROM GroupedNames
WHERE RowNum > 1
Maybe this would work?
SELECT id FROM table WHERE id NOT IN (SELECT MIN(id) FROM table GROUP BY name)
SELECT DISTINCT b.id
FROM yourTable a
JOIN yourTable b
ON a.name = b.name
AND a.id < b.id