【问题标题】:CASE in WHERE CLAUSE in MYSQLMYSQL 中 WHERE CLAUSE 中的 CASE
【发布时间】:2014-03-06 14:02:08
【问题描述】:

问题就像标题所说的那样简单,但这是一个逻辑。 这是我的代码

CREATE TABLE `inf_brand_images` (
`id` bigint(99) NOT NULL AUTO_INCREMENT,
`brand` varchar(255) NOT NULL,
`thumb` text NOT NULL,
`is_active` int(2) NOT NULL DEFAULT '1',
`cmp_brand` varchar(1024) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6458 DEFAULT CHARSET=latin1

这是该表中的数据

ID | brand  | thumb  |is_active| cmp_brand
1  | NIKE   | a.png  | 1       | 
2  | DUNHILL| b.png  | 1       |
3  | NIKE   | c.png  | 1       | 123_NIKE
4  | NIKE   | d.png  | 1       | 789_NIKE

cmp_brand 在我的例子中以 123_ 和 789_ 之类的 id 为前缀。 现在如果我搜索 NIKE,所以我有两个参数,一个是 NIKE,另一个是 id_NIKE。其中 id 可能是 123 或 456 或任何其他。所以对于 NIKE 搜索我有两个参数,一个是品牌 = NIKE,另一个是 cmp_brand =123_NIKE(我可以自动将 id 与品牌名称连接起来)

我想要的是

IF cmp_brand is '' then compare with brand ELSE compare brand AND cmp_brand.

这是我试过的,都不起作用

SELECT thumb 
FROM inf_brand_images 
where is_active=1  AND 
CASE WHEN cmp_brand = '' THEN brand='NIKE' 
ELSE cmp_brand='123_NIKE' END

 SELECT thumb 
 FROM inf_brand_images 
 where is_active=1 AND 
((cmp_brand = '' AND brand='NIKE') OR (cmp_brand='123_NIKE'))

【问题讨论】:

  • 我希望您的第二个查询能够正常工作。这是处理它的正确方法(逻辑分组 AND/OR,不是 CASE)sqlfiddle.com/#!2/d176b
  • 对于此查询,您是否期望得到与 ID=1, ID=3 不同的结果?根据我的阅读,这是预期的结果。
  • 第二个查询给我记录号 1,3 但我只需要 3.mean 我只需要 c.png
  • 好的,所以您想首选 cmp_brand 匹配而不是brand 匹配?
  • 当心!有时 rdms 系统将零长度字符串表示为 NULL 值。在这种情况下,column = '' 不会是真的,但column IS NULL 会是。

标签: mysql case where clause


【解决方案1】:

您在第二次尝试时走在正确的轨道上,使用逻辑 AND/OR 分组而不是 CASE,但如果您想更喜欢匹配 cmp_brand 的行而不是带有为空 cmp_brand 并期望只返回一个结果,构造您的 ORDER BY 以首先对非空 cmp_brand 进行排序,并将整体结果限制为 1。

SELECT thumb 
FROM inf_brand_images 
WHERE
  is_active=1 AND 
  ((cmp_brand = '' AND brand='NIKE') OR (cmp_brand='123_NIKE'))
/* non-empty cmp_brand will sort first */
ORDER BY cmp_brand <> '' DESC
/* and the end result is limited only to the first sorted row
   which will be the cmp_brand if matched, or the brand otherwise */
LIMIT 1

http://sqlfiddle.com/#!2/d176b/2

这是因为表达式 cmp_brand &lt;&gt; '' 计算为布尔值 true/false,MySQL 将其解释为 1/0。对这些值进行降序排序会强制非空值排序(1 在 0 之前)。

cmets 后更新:

由于您确实有可能返回不止一行,因此您不能依赖ORDER BY。相反,您可以对同一个表执行LEFT JOIN。一方面匹配cmp_brand = '',另一方面匹配cmp_brand = '123_NIKE'。重要的是,从连接的双方返回thumb 列。

将其包装在 FROM 子句中的子查询中,然后在顶层您可以使用 SELECT CASE 来首选 cmp_brand(如果非空)。

SELECT DISTINCT
  CASE WHEN cbcb IS NOT NULL THEN cbthumb ELSE bthumb END AS thumb
FROM (
  /* Return thumbs from both sides of the join */
  SELECT 
    b.thumb AS bthumb,
    b.cmp_brand AS bcb,
    cb.thumb AS cbthumb,
    cb.cmp_brand AS cbcb
  FROM
    inf_brand_images b
    /* join the table against itself with the matching cmp_brand in the join condition */
    LEFT JOIN inf_brand_images cb
      ON b.brand = cb.brand
      AND cb.cmp_brand = '123_NIKE'
  WHERE 
    /* The WHERE clause looks for empty cmp_brand on the left side of the join */
    b.brand = 'NIKE' AND b.cmp_brand = ''
) thumbs

【讨论】:

  • @Micheal:这很好,但是如果我想获得更多记录,那么它会给我错误的数据......例如,如果我有另一条记录,“(5,'NIKE',' e.png', 1, '123_NIKE')" 那么它将不起作用。简单的是如果 cmp_brand'' 那么我不需要显示/检查品牌
  • 我的问题很清楚,如果cmp_brand匹配则不需要比较品牌。如果cmp_brand不匹配则需要比较品牌。
  • @user3244721 好的,如果您需要返回更多行,这有点复杂,但我找到了一个可行的方法。
猜你喜欢
  • 2020-09-13
  • 2023-04-11
  • 2010-10-22
  • 1970-01-01
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多