MySQL Select, 单列唯一
MySQL Select, unique in one column
假设我有一个 table 具有以下 rows/values:
我需要一种方法来 select 数量中的值,但如果它们重复则只需要一次。因此,从这个例子中,我想 select A、B 和 C 一次。 SQL 结果应该如下所示:
您可以根据需要使用不同的功能处理此类情况:
案例 1 : 如果每个名称具有相同的值:
select distinct name, amount from [table name]
案例 2 : 您有重复项,每个名称的值都不同,您想要选择值最高的那个。如果您需要最少的人出现,请使用 min()
。
select name, max(amount) from [table name] group by 1
案例 3: 你需要的那个,剩下的重复部分有空白。
- 行号将根据金额的值创建行,并且由于值相同,因此将逐步创建它,然后您可以使用
IF
创建一个新列 where rank_ > 1 then blanks
。这也将涵盖您希望 select 只是最小值然后为其余名称值留空的情况
With ranking as (
select
*,
ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY AMOUNT) AS RANK_
from [table]
)
SELECT
*,
IF(RANK_ > 1,"",AMOUNT) AS NEW_AMOUNT
FROM ranking
情况4:你需要select最大,其他名字留空
- 您只需将
order by clause of ROW_NUMBER()
调整为 DESC
。这将使排名 1 达到每个名称的最高金额,其余的将填充空白
With ranking as (
select
*,
ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY AMOUNT DESC) AS RANK_
from [table]
)
SELECT
*,
IF(RANK_ > 1,"",AMOUNT) AS NEW_AMOUNT
FROM ranking
使用 LAG() 函数并将名称的先前金额与当前行金额进行比较。
-- MySQL (v5.8)
SELECT t.name
, CASE WHEN t.amount = t.prev_val THEN '' ELSE amount END amount
FROM (SELECT *
, LAG(amount) OVER (PARTITION BY name ORDER BY name) prev_val
FROM test) t
请从urlhttps://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=8c1af9afcadf2849a85ad045df7ed580
检查
如果您使用的是 mysql 8,则可以使用 row_number
:
with x as (
select *, row_number() over(partition by name order by amount) rn
from t
)
select name, case when rn=1 then amount else '' end amount
from x
其他答案遗漏了一个非常重要的点:A SQL table returns 一个 unordered 集,除非有明确的 order by
.
您提供的数据包含完全重复的行。出于这个原因,我认为最好的方法是在外部查询中使用 row_number()
和 order by
:
select name, (case when seqnum = 1 then amount end) as amount
from (select t.*,
row_number() over (partition by name, amount) as seqnum
from t
) t
order by name, seqnum;
请注意 MySQL 不需要 row_number()
的 order by
参数。
不过,更常见的是,您会有一些其他列(例如日期或 ID)用于订购。我还应该强调,这种类型的格式化通常在应用层处理,而不是在数据库中处理。
假设我有一个 table 具有以下 rows/values:
我需要一种方法来 select 数量中的值,但如果它们重复则只需要一次。因此,从这个例子中,我想 select A、B 和 C 一次。 SQL 结果应该如下所示:
您可以根据需要使用不同的功能处理此类情况:
案例 1 : 如果每个名称具有相同的值:
select distinct name, amount from [table name]
案例 2 : 您有重复项,每个名称的值都不同,您想要选择值最高的那个。如果您需要最少的人出现,请使用 min()
。
select name, max(amount) from [table name] group by 1
案例 3: 你需要的那个,剩下的重复部分有空白。
- 行号将根据金额的值创建行,并且由于值相同,因此将逐步创建它,然后您可以使用
IF
创建一个新列where rank_ > 1 then blanks
。这也将涵盖您希望 select 只是最小值然后为其余名称值留空的情况
With ranking as (
select
*,
ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY AMOUNT) AS RANK_
from [table]
)
SELECT
*,
IF(RANK_ > 1,"",AMOUNT) AS NEW_AMOUNT
FROM ranking
情况4:你需要select最大,其他名字留空
- 您只需将
order by clause of ROW_NUMBER()
调整为DESC
。这将使排名 1 达到每个名称的最高金额,其余的将填充空白
With ranking as (
select
*,
ROW_NUMBER() OVER(PARTITION BY NAME ORDER BY AMOUNT DESC) AS RANK_
from [table]
)
SELECT
*,
IF(RANK_ > 1,"",AMOUNT) AS NEW_AMOUNT
FROM ranking
使用 LAG() 函数并将名称的先前金额与当前行金额进行比较。
-- MySQL (v5.8)
SELECT t.name
, CASE WHEN t.amount = t.prev_val THEN '' ELSE amount END amount
FROM (SELECT *
, LAG(amount) OVER (PARTITION BY name ORDER BY name) prev_val
FROM test) t
请从urlhttps://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=8c1af9afcadf2849a85ad045df7ed580
检查如果您使用的是 mysql 8,则可以使用 row_number
:
with x as (
select *, row_number() over(partition by name order by amount) rn
from t
)
select name, case when rn=1 then amount else '' end amount
from x
其他答案遗漏了一个非常重要的点:A SQL table returns 一个 unordered 集,除非有明确的 order by
.
您提供的数据包含完全重复的行。出于这个原因,我认为最好的方法是在外部查询中使用 row_number()
和 order by
:
select name, (case when seqnum = 1 then amount end) as amount
from (select t.*,
row_number() over (partition by name, amount) as seqnum
from t
) t
order by name, seqnum;
请注意 MySQL 不需要 row_number()
的 order by
参数。
不过,更常见的是,您会有一些其他列(例如日期或 ID)用于订购。我还应该强调,这种类型的格式化通常在应用层处理,而不是在数据库中处理。