【问题标题】:MySQL Select, unique in one columnMySQL Select,在一列中唯一
【发布时间】:2021-11-09 09:35:18
【问题描述】:

假设我有一个包含以下行/值的表:

我需要一种方法来选择数量值,但如果它们被重复,则只选择一次。所以从这个例子中,我想选择 A、B 和 C 的金额一次。 SQL 结果应如下所示:

【问题讨论】:

  • 空条目有什么用?简单地选择distinct 不会产生更好的结果吗?为什么会有这些重复项?这让我想知道是否已经出现了问题(可能是设计有缺陷?)。
  • 你需要的不仅仅是你所展示的,表格的主键是什么?你的mysql版本是多少?
  • 您考虑过选择name, amount, count(*)吗?
  • 你用的是哪个版本的mysql?

标签: mysql sql select


【解决方案1】:

您可以根据需要使用不同的功能处理此类情况:

案例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。这也将涵盖您只想选择最小值然后为其余名称值留空的情况
    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:您需要选择最大值并将其他名称留空

  • 您只需将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

【讨论】:

  • 对于案例 3 - 添加 ORDER BY name, amount, rank_。如果没有这个,行可能会在外部查询中重新排序失败。
  • @Akina 因为值相同,所以 ASC 的相同顺序可以正常工作,但是如果要求获得最大值而其余为空白,则需要 desc 顺序
  • 我查看所需的输出。显然 OP 想要形成分组输出,在这种情况下,amount 中的值的行需要是组中的最上层。
  • 我已添加所有案例
【解决方案2】:

使用 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

请查看网址https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=8c1af9afcadf2849a85ad045df7ed580

【讨论】:

    【解决方案3】:

    如果您使用的是 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
    

    example Fiddle

    【讨论】:

      【解决方案4】:

      其他答案遗漏了一个非常重要的点:除非有明确的order by,否则 SQL 表会返回一个 无序 集。

      您提供的数据具有完全相同的行。出于这个原因,我认为最好的方法是在外部查询中使用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;
      

      请注意,对于 row_number(),MySQL 不需要 order by 参数。

      不过,更常见的是,您会有一些其他列(例如日期或 ID)用于订购。我还应该强调的是,这种类型的格式化通常是在应用层而不是在数据库中处理的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-19
        • 1970-01-01
        • 1970-01-01
        • 2014-10-21
        • 2018-01-21
        • 2012-07-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多