根据name字段的最大值(char\u length),从连接中的每个组中选择一条记录

plupiseo  于 2021-06-21  发布在  Mysql
关注(0)|答案(4)|浏览(312)

给定一个查询,其中我在一个表中根据与另一个表的匹配情况查找“name”字段,如何将匹配项保留在长度最长的第一个表中?我知道 Max(Char_Length) 可能是找到最长的但不确定如何归还的方法:
http://sqlfiddle.com/#!9/2b8b7fa/3号

Select ID,T1.Name from ShortNames T1
Inner Join LongNames T2
On T2.Name Like Concat('% ', T1.Name)
or T2.Name like Concat(T1.Name,' %')
at0kjp5o

at0kjp5o1#

如果需要所有列,可以在子选择的where中检查最大长度

Select ID,T1.Name 
  from ShortNames T1
  Inner Join LongNames T2
  On T2.Name Like Concat('% ', T1.Name)
  or T2.Name like Concat(T1.Name,' %')

  where length(T1.Name from) = (
    Select max(length(T1.Name from)) 
    FROM ShortNames T1
    Inner Join LongNames T2
    On T2.Name Like Concat('% ', T1.Name)
    or T2.Name like Concat(T1.Name,' %')
  )
7nbnzgx9

7nbnzgx92#

这是每个组最大n个问题的一个变体,这个问题在堆栈溢出时经常被问到。
有一种方法可以解决这个问题:

SELECT ID, T1.Name FROM ShortNames T1
INNER JOIN LongNames T2
  ON T2.Name LIKE CONCAT('% ', T1.Name)
  OR T2.Name LIKE CONCAT(T1.Name,' %')
LEFT OUTER JOIN LongNames T3
  ON (T3.Name LIKE CONCAT('% ', T1.Name)
  OR T3.Name LIKE CONCAT(T1.Name,' %'))
  AND CHAR_LENGTH(T3.NAME) > CHAR_LENGTH(T2.NAME)
WHERE T3.NAME IS NULL;

说明:对另一个名称比t2长的行t3使用外部联接。如果没有找到,那么t2必须是名称最长的。
不幸的是,如果存在联系,这将返回多个结果。
在mysql 8.0中,它们支持窗口函数和CTE,所以这个问题可以用另一种方法解决(我还没有测试过这个):

WITH ranked_names AS (
  SELECT T1.ID, T1.Name, ROW_NUMBER() 
    OVER (PARTITION BY T1.Name ORDER BY CHAR_LENGTH(T2.Name) DESC) AS rownum
  FROM ShortNames T1
  INNER JOIN LongNames T2
    ON T2.Name LIKE CONCAT('% ', T1.Name)
    OR T2.Name LIKE CONCAT(T1.Name,' %')
)
SELECT * FROM ranked_names WHERE rownum = 1;

即使出现平局,也不会返回多个结果。
第三种解决方案是在shortnames表中保留一列,该列引用longnames中的首选行。

ALTER TABLE ShortNames ADD COLUMN LongestNameId INT;

填充该列后,可以执行更简单的联接:

SELECT ID, T1.Name, T2.Name FROM ShortNames T1
INNER JOIN LongNames AS T2
  ON T1.LongestNameID = T2.ID

它将以比您的查询更好的性能运行 LIKE 模式匹配。

ijnw1ujt

ijnw1ujt3#

如您所述,您可以使用max函数:

Select Max(T1.Name) from ShortNames T1
Inner Join LongNames T2
On T2.Name Like Concat('% ', T1.Name)
or T2.Name like Concat(T1.Name,' %')
uinbv5nw

uinbv5nw4#

我讨厌回答我自己的问题:|但这似乎起到了预期的作用:
http://sqlfiddle.com/#!9/2b8b7fa/13号 Select T2.ID,T1.Name from ShortNames T1 Inner Join LongNames T2 On T2.Name Like Concat('% ', T1.Name) or T2.Name like Concat(T1.Name,' %') Group by T2.ID Order by Max(Char_Length(T1.Name))

相关问题