SQL SELECT 名称 LIKE $name 但不完全相同的名称两次

Posted

技术标签:

【中文标题】SQL SELECT 名称 LIKE $name 但不完全相同的名称两次【英文标题】:SQL SELECT names LIKE $name but not exact same name twice 【发布时间】:2013-09-13 01:47:08 【问题描述】:

我正在使用此 SQL 查询来遍历表并搜索客户名称并返回该行的 id 和日期列:

SELECT custName, date, id FROM booking
WHERE custName LIKE '%$s'
OR custName LIKE '$s%'

($s 是一个 php 变量)

如果我正在寻找 John Dorian,我可以输入 $s 作为名字 John 或姓氏 Dorian,我的函数会找到他。我的问题是 John Dorian 可能出现在多行中,如果是这种情况,我希望查询只返回最近的行(使用日期列来解决这个问题)。

IE 如果我的表看起来像这样并且 $s = John:

(custName, date, id)
John Dorian - 2013/01/01 - 1
John Doe - 2013/01/02 - 2
John Dorian - 2013/01/10 - 3

我希望我的查询返回

John Doe - 2013/01/02 - 2
John Dorian - 2013/01/10 - 3

【问题讨论】:

你应该选择一个正确的答案。 【参考方案1】:

怎么样:

SELECT custName, date, id 
FROM booking b
INNER JOIN
(
    SELECT max(date) MaxDate, custName
    FROM booking
    WHERE custName LIKE '%$s%'
    GROUP BY custName
) bm
  ON b.custName = bm.custName
  AND b.date = bm.maxDate
WHERE custName LIKE '%$s%'
ORDER BY b.date DESC

【讨论】:

需要聚合非组列【参考方案2】:

1) 您可以使用DISTINCTGROUP BY 轻松搜索并获取每位客户的一行:

SELECT DISTINCT custName
FROM booking
WHERE custName LIKE '%$s' OR custName LIKE '$s%';

SELECT custName
FROM booking
WHERE custName LIKE '%$s' OR custName LIKE '$s%'
GROUP BY custName;

2) 您可以通过将聚合函数(即MAX)与GROUP BY 耦合来获得最大日期

SELECT custName, MAX(date) as date
FROM booking
WHERE custName LIKE '%$s' OR custName LIKE '$s%'
GROUP BY custName;

3) 最后,您可以通过将结果连接回原始表来获得完整的表行:

SELECT b.custName, b.date, b.id
FROM booking AS b
INNER JOIN
    (SELECT custName, MAX(date) AS maxDate
    FROM booking
    WHERE custName LIKE '%$s' OR custName LIKE '$s%'
    GROUP BY custName
    ) AS gb
ON b.custName = gb.custName AND b.date = gb.maxDate;

或(可能更慢):

SELECT b.custName, b.date, b.id
FROM booking AS b
INNER JOIN
    (SELECT custName, MAX(date) AS maxDate
    FROM booking
    GROUP BY custName
    ) AS gb
ON b.custName = gb.custName AND b.date = gb.maxDate
WHERE b.custName LIKE '%$s' OR b.custName LIKE '$s%';

附言

以下内容可能看起来很有希望,有时甚至可能给出正确的结果,但不能保证有效。

SELECT *
FROM (
   SELECT custName, date, id
   FROM booking
   WHERE b.custName LIKE '%$s' OR b.custName LIKE '$s%'
   ORDER BY date DESC
) AS t
GROUP BY custNAME;

很遗憾,您不能依靠GROUP BY 来维持提供的订单。

编辑另见

mysql order by before group by How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL? http://ftp.nchu.edu.tw/MySQL/tech-resources/articles/debunking-group-by-myths.html

【讨论】:

【参考方案3】:

我认为您需要在 custName 列上有一个不同的值。虽然我自己没有尝试过,但我认为 BadWolf 的答案会返回名为“John Dorian”的两行:

SELECT distinct(custName), date, id FROM booking WHERE 
custname LIKE '%$s%' 
GROUP BY custName, date, id
ORDER BY date DESC

【讨论】:

这没有多大意义。如果您 GROUP BY 全部三个值(custName、日期和 id),那么您可能根本不使用 GROUP。 我喜欢这个,因为它比其他解决方案简单得多。我只按 custName 分组(按所有三个分组没有返回任何结果)。同样在此刻,我只得到最旧的行,而不是最新的。我尝试按日期 asc/desc 排序,但无济于事。稍后会尝试更多。 它可能更简单,但实际上并不能正常工作。 GROUP BY 在未提供聚合函数时任意选择行值。在此查询中,GROUP BY 发生在 ORDER BY 之前,因此在对行进行排序之前已经(任意)选择了 dateid 值。但是,即使您首先 将结果排序到内部SELECT,然后将结果分组到外部“SELECT”中,也不能保证有效。请参阅我的解决方案和this article。【参考方案4】:

乍一看,我以为这是一个简单的问题,但我错了。

我只能通过follow语句来解决。

select * from 
   (SELECT custName, date, id FROM booking 
          WHERE custName LIKE '%$s' OR 
          custName LIKE '$s%' order by date desc) as t 
   group by (t.custName) order by date ;

它可能有其他更好的解决方案。

【讨论】:

以上是关于SQL SELECT 名称 LIKE $name 但不完全相同的名称两次的主要内容,如果未能解决你的问题,请参考以下文章

like语句防止SQL注入

关于sql查询中的like用法疑问?

数据库查询语句SQL中like%-的区别

sql查询之模糊查询

Sql语句中Like嵌套用法

sql中"select ...like '%%' "问题,高手请进!!