I want to get some column based on another column
Example table:
| BlilCode | BlilShortName | BatchWeigth | BillVersion | BlilMaxTime |
+----------+---------------+-------------+-------------+-------------+
| 5502 | aaa | 1.00 | 1 | 360 |
| 5502 | aaa | 2.00 | 2 | 240 |
| 5510 | bbb | -32.94 | 2 | 360 |
| 5510 | bbb | 1.00 | 1 | 360 |
| 5510 | bbb | 36.37 | 3 | 3600 |
but I want to get the rows where BillVersion
is max for every BlilCode
is max
Expected result
| BlilCode | BlilShortName | BatchWeigth | BillVersion | BlilMaxTime |
+----------+---------------+-------------+-------------+-------------+
| 5502 | aaa | 2.00 | 2 | 240 |
| 5510 | bbb | 36.37 | 3 | 3600 |
My current query is:
SELECT
[BlilCode], [BlilShortName],
BatchWeigth, (BillVersion) AS BillVersion, [BlilMaxTime]
FROM
[CVfeedDB].[dbo].[constants.Blil]
WHERE
BlilActive = 1 AND BatchWeigth IS NOT NULL
ORDER BY
BlilCode
I'm not really smart from your description, however, the result can be achieved using the following query
select your_table.*
from your_table
join
(
select BlilShortName, max(billversion) bmax
from your_table
group by BlilShortName
) t on your_table.billversion = t.bmax and your_table.BlilShortName = t.BlilShortName
From my experience it can be faster in some cases when compared to row_number
solution which always uses sequential scan.
PERFORMANCE BONUS
Since there is a discussion regarding the efficiency I dare to add simple test
IF OBJECT_ID('dbo.GTable', 'U') IS NOT NULL DROP TABLE dbo.GTable
SELECT TOP 1000000
NEWID() id,
ABS(CHECKSUM(NEWID())) % 100 group_id,
ABS(CHECKSUM(NEWID())) % 10000 orderby
INTO GTable
FROM sys.sysobjects
CROSS JOIN sys.all_columns
SET STATISTICS TIME on
-- GROUP BY version
select t1.*
from gtable t1
join
(
SELECT group_id, max(orderby) gmax
from gtable
group by group_id
) t2 on t1.group_id = t2.group_id and t1.orderby = t2.gmax
-- WINDOW FUNCTION version
select t.id, t.group_id, t.orderby
from
(
select *,
dense_rank() over (partition by group_id order by orderby desc) rn
from gtable
) t
where t.rn = 1
If I run this on my server then the performance of GROUP BY version is more than twice better than the window function version. Moreover, if I create index
CREATE NONCLUSTERED INDEX ix_gtable_groupid_orderby
ON [dbo].[GTable] (group_id,orderby) INCLUDE (id)
then the performance is even more than three times better, whereas the performance of window function solution is the same since it uses sequential scan despite the index.
Your results suggest that you want:
select db.*
from (select db.*,
row_number() over (partition by shortname order by billversion desc) as seqnum
from db
) db
where seqnum = 1;
If you based this on blilcode
, then the results would have three rows instead of two.
Note: The question was edited after this, so the appropriate query would be:
select db.*
from (select db.*,
row_number() over (partition by blilcode order by billversion desc) as seqnum
from db
) db
where seqnum = 1;
来源:https://stackoverflow.com/questions/47674876/select-corresponding-to-row-from-the-same-table-sql-server