SQL | Return MIN values | multiple rows dynamically

筅森魡賤 提交于 2021-01-28 03:20:22

问题


I need to create a query that returns only the rows which have the minimum values in a specific column.

I have this results (example):

Name  |  Description  | Order
-----------------------------
Name1 |  A            | 1
Name1 |  B            | 2
Name1 |  C            | 3
Name2 |  A            | 1
Name2 |  B            | 2
Name2 |  C            | 3

I want to get this results:

Name  |  Description  | Order
-----------------------------
Name1 |  A            | 1
Name2 |  A            | 1

Basically, I need to select only the rows which have the minimum value in the column order.

I'm stuck with queries like Query A:

Select Top 1 *
From table1
Where Name = 'Name1'
Order by Order

Or Query B:

Select *
From table1
Where Name = 'Name1'
 and order = (Select min(Order)
              From table1
              Where Name = 'Name1')

What I need is to have in a single query, the capability of returning the rows for multiple names, instead of having to do queries per name. Is there any way, to pass attributes values to the subquery in the example of Query B?

What are the alternatives?

The platform is SQL Server 2012.


回答1:


You're close on the second query if you want to use a simple subquery:

Select *
From table1 t1
WHERE [order] = (Select min([Order])
             From table1
             Where Name = t1.Name)

You can also use partitioning functions to find the "first" record for each group:

SELECT Name, Description, [Order] FROM
    (SELECT *,
        ROW_NUMBER() OVER(ORDER BY [Order] PARTITION BY Name) RowNum
     FROM Table1 
    ) A
WHERE RowNum = 1



回答2:


A better way

select * 
from
(
select row_number()over(partition by Name order by [Order] ASC) as Rn,* 
from yourtable
) A
Where RN = 1

Or Using INNER JOIN. First find the min order per Name and join the result back to the original table

SELECT * 
FROM   table1 A 
       INNER JOIN (SELECT [order] = Min(order), 
                          name 
                   FROM   table1 
                   WHERE  name = t1.name 
                   GROUP  BY name) B 
               ON A.[order] = B.[order] 
                  AND A.name = B.name 

Using Min() aggregate with partition by window function

select * 
from
(
select Min([Order])over(partition by Name) as min_order,* 
from yourtable
) A
Where min_order = [Order]


来源:https://stackoverflow.com/questions/34596359/sql-return-min-values-multiple-rows-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!