SQL group need related value instead of aggregate function - sql-server

Have a table like this
FileID Value Version
-------------------------
1 Welle 2
1 Achse 3
2 Box 5
2 Enclosure 7
I need to "sum" up the lines with same FileID -> take highest value from column VERSION and get back the related value.
Desired result would be:
FileID Value Version
-------------------------
1 Achse 3
2 Enclosure 7
However using GROUP By sums up, but brings wrong result for Value:
SELECT
[FileID],
MAX([Value]),
MAX([Version])
FROM [ValueMist]
GROUP BY FileID
This returns:
FileID Value Version
------------------------
1 Welle 3
2 Enclosure 7

One option is WITH TIES in concert with row_number()
Example
Select top 1 with ties *
From YourTable
Order By row_number() over (partition by FileId Order By version desc)

You can achieve this by using ROW NUMBER
;WITH CTE AS (SELECT ROW_NUMBER() OVER ( PARTITION BY
ID ORDER BY VERSION DESC) AS RW
FROM TABLE)
SELECT * FROM CTE
WHERE RW=1

Related

How to select the value from the table based on category_id USING SQL SERVER

How to select the value from the table based on category_id?
I have a table like this. Please help me.
Table A
ID Name category_id
-------------------
1 A 1
2 A 1
3 B 1
4 C 2
5 C 2
6 D 2
7 E 3
8 E 3
9 F 3
How to get the below mentioned output from table A?
ID Name category_id
--------------------
1 A 1
2 A 1
4 C 2
5 C 2
7 E 3
8 E 3
Give a row number for each row based on group by category_id and sort by ascending order of ID. Then select the rows having row number 1 and 2.
Query
;with cte as (
select [rn] = row_number() over(
partition by [category_id]
order by [ID]
), *
from [your_table_name]
)
select [ID], [Name], [category_id]
from cte
where [rn] < 3;
Kindly run this query It really help You Out.
SELECT tbl.id,tbl.name, tbl.category_id FROM TableA as tbl WHERE
tbl.name IN(SELECT tbl2.name FROM TableA tbl2 GROUP BY tbl2.name HAVING Count(tbl2.name)> 1)
Code select all category_id from TableA which has Name entries more then one. If there is single entry of any name group by category_id then such data will be excluded. In above example questioner want to eliminate those records that have single Name entity like wise category_id 1 has name entries A and B among which A has two entries and B has single entry so he want to eliminate B from result set.

Sql server Getting the difference starting from top

Actually what i need was something like this : i have one row with so many columns, and my script should calculate the difference starting from the highest and the second highest, then 2nd highest and 3rd one.. it goes like that.
Well Sql server can't even calculate the maximum value in a row ( it can calculate max in one column as i know )
So i used pivot for my table and now i have one column. I ordered them from max to lowest, now what i need is, how will i get the diffence :first value minus second value, second value minus third value...
A couple of ways you can do this - and you should read up sql server analytic and window functions.
Given
DROP TABLE T
CREATE TABLE T (ID INT)
INSERT INTO T VALUES
(1),(10),(2),(5)
You could use the lag analytic function
SELECT ID ,
LAG(ID, 1,0) OVER (ORDER BY ID DESC) LAGID,
ID - LAG(ID, 1,0) OVER (ORDER BY ID DESC) DIFF
FROM T
result
ID LAGID DIFF
----------- ----------- -----------
10 0 10
5 10 -5
2 5 -3
1 2 -1
(4 row(s) affected)
or using the row_number() window function
SELECT TID,TRN,UID,URN, TID - UID AS DIFF
FROM
(
SELECT T.ID TID
,ROW_NUMBER() OVER (ORDER BY T.ID DESC) TRN
FROM T
) S
LEFT JOIN
(SELECT ID UID
,ROW_NUMBER() OVER (ORDER BY ID DESC) URN
FROM T
) U
ON URN = TRN - 1
result
TID TRN UID URN DIFF
----------- -------------------- ----------- -------------------- -----------
10 1 NULL NULL NULL
5 2 10 1 -5
2 3 5 2 -3
1 4 2 3 -1
(4 row(s) affected)

Select randomly few Rows of the same ID in the same table (T-SQL)

I'm trying to select randomly few rows for each Id stored in one table where these Ids have multiple rows on this table. It's difficult to explain with words, so let me show you with an example :
Example from the table :
Id Review
1 Text11
1 Text12
1 Text13
2 Text21
3 Text31
3 Text32
4 Text41
5 Text51
6 Text61
6 Text62
6 Text63
Result expected :
Id Review
1 Text11
1 Text13
2 Text21
3 Text32
4 Text41
5 Text51
6 Text62
In fact, the table contains thousands of rows. Some Ids contain only one Review but others can contain hundreds of reviews. I would like to select 10% of these, and select at least once, all rows wich have 1-9 reviews (I saw the SELECT TOP 10 percent FROM table ORDER BY NEWID() includes the row even if it's alone)
I read some Stack topics, I think I have to use a subquery but I don't find the correct solution.
Thanks by advance.
Regards.
Try this:
DECLARE #t table(Id int, Review char(6))
INSERT #t values
(1,'Text11'),
(1,'Text12'),
(1,'Text13'),
(2,'Text21'),
(3,'Text31'),
(3,'Text32'),
(4,'Text41'),
(5,'Text51'),
(6,'Text61'),
(6,'Text62'),
(6,'Text63')
;WITH CTE AS
(
SELECT
id, Review,
row_number() over (partition by id order by newid()) rn,
count(*) over (partition by id) cnt
FROM #t
)
SELECT id, Review
FROM CTE
WHERE rn <= (cnt / 10) + 1
Result(random):
id Review
1 Text12
2 Text21
3 Text31
4 Text41
5 Text51
6 Text63

Get the count of a value for each row in SQL

I have a SQL question. Below is my data and query
select ID from table
ID
4
4
5
3
5
3
3
What query should I add to my select list so that it gives me the occurrence of a value for each specfic row(I do not want the total count, I want something like a rank of occurrence).
4 1--this is the first time we got a 4 in the list, so 1
4 2--this is the second time we got a 4 in the list, so 2
5 1--this is the first time we got a 5 in the list, so 1
3 1--this is the first time we got a 3 in the list, so 1
5 2--this is the second time we got a 5 in the list, so 2
3 2--this is the second time we got a 3 in the list, so 2
3 3--this is the third time we got a 3 in the list, so 3
You want ROW_NUMBER():
SELECT
[Id],
ROW_NUMBER() OVER (PARTITION BY [Id] ORDER BY [Id])
FROM ...
You'll probably need to change the Order By clause to get the right output.
To generate a numbering from an order of rows, use row_number() or rank(). The problem is, row_number() does not guarantee the original order will be preserved. You could try this:
select
[id],
row_number() over (partition by id, order by (select 1)) as [rank]
from #t
However, you will find the results are not in the original order and somewhat confusing:
id rank
3 1
3 2
3 3
4 1
4 2
5 1
5 2
To preserve the original row order, you could build a temporary table or table variable with an identity column. Select a row_number() partitioned by id from there:
declare #t table ([tkey] int identity(1,1) primary key clustered, [id] int)
insert into #t (id) values (4), (4), (5), (3), (5), (3), (3)
select
[id],
row_number() over (partition by [Id] order by [tkey]) as [rank]
from #t
order by [tkey]
Note that the final order by [tkey] really is necessary. The query has the desired results:
id rank
4 1
4 2
5 1
3 1
5 2
3 2
3 3
Here is a Common Table Expression (CTE) approach. The CTE adds a row_number() to maintain the rows in the original order. (This is the equivalent of the identity column in the previous example.) The actual ranking comes with the second row_number() when it does a partition by id. This causes the 1st 4 gets 1, the 2nd 4 gets 2, etc.
The second row_number() must be ordered by the original order to rank correctly, but this is still not enough to preserve the order in the output. A final order by ensures the ending order is the same.
declare #t table (id int)
insert into #t (id) values (4), (4), (5), (3), (5), (3), (3)
;with [tRows] (rownum, id) as
(
select
row_number() over (order by (select 1)) as [rownum],
[id]
from #t
)
select
[id],
row_number() over (partition by id order by [rownum]) as [rank]
from [tRows]
order by [rownum]
This query also has the desired results:
id rank
4 1
4 2
5 1
3 1
5 2
3 2
3 3
In this example, you could use rank() instead of the second row_number(). The difference between the functions is explained well in this question. rank() would not work the same if, somehow, there were duplicate row numbers generated by the first row_number(), but that cannot happen.

Using a While Loop to update a field by 1 each time a value changes

So I have a table that has two records that need to be one. I can identify them but I want to update them in groups (sort of like a scan update =1, then proceed, then some other field changes, increment the number by 1 and proceed.)
Example table:
IDEvent 1 2 3 4 5
Col1 1 1 0 1 0
Col2 a a b a b
So essentially, my outcome would look like this afterwards so that I can write a select and group by col1 to then group the two first records into one but leave non consecutive record alone. I tried while loops but I couldn't figure it out.
IDEvent 1 2 3 4 5
Col1 1 1 0 2 0
Col2 A A B A B
alter view PtypeGroup as
WITH q AS
(
SELECT *,
ROW_Number() OVER (PARTITION BY idsession, comment ORDER BY ideventrecord) AS rnd,
ROW_NUMBER() OVER (PARTITION BY idsession ORDER BY ideventrecord) AS rn
FROM [ratedeventssorted]
)
SELECT min(ideventrecord) as IDEventRecord, idsession, min(distancestamp) as distancestamp, sum(length) as length, min(comment) as comment2, min(eventscorename) as firstptype, min(eventscoredescription) as Ptype2,
MIN(ideventrecord) AS first_number,
MAX(ideventrecord) AS last_number,
comment
,COUNT(ideventrecord) AS numbers_count
--into test
FROM q
where eventscorename IN ('Flex', 'Chpsl')
GROUP BY idsession,
rnd - rn,
comment

Resources