依靠来自同一列的各种子串

时间:2012-07-06 09:17:23

标签: mysql sql count

我想计算来自同一列并具有相同WHERE条件的多个子串的出现次数。对于每个子字符串,我有一个UNION SELECT语句,包括重复的WHERE条件。最终结果是使用appox进行查询。 2500行的sql代码,但它给出了很好的结果。

查询的简化示例:

SELECT ‘be’ AS country, count(destination) FROM demo
WHERE destination LIKE ‘%be%’ AND field_a=xzx AND field_b=bbb

UNION SELECT ‘de’ AS country, count(destination) FROM demo
WHERE destination LIKE ‘%de%’ AND field_a=xzx AND field_b=bbb

UNION SELECT ‘fr’ AS country, count(destination) FROM demo
WHERE destination LIKE ‘%fr%’ AND field_a=xzx AND field_b=bbb

UNION SELECT ‘nl’ AS country, count(destination) FROM demo
WHERE destination LIKE ‘%nl%’ AND field_a=xzx AND field_b=bbb

是否可以修改查询,使WHERE条件仅在查询中出现一次?

请通过以下链接找到我的问题的简化示例:

https://docs.google.com/document/d/1otjZZlBy6au5E2I7T6NdSYmLayhNGWyXGxGo3gBx_-w/edit

3 个答案:

答案 0 :(得分:1)

不要 在单个字段中存储逗号分隔值。相反,使用many:many关系表并每行存储一个(id,country)组合。您的数据结构是SQL-Anti-Pattern,违反了所有关系数据库设计原则。

CREATE TABLE map (
  demo_id INT,
  country VARCHAR(2),
  PRIMARY KEY (demo_id, country)
)

INSERT INTO map VALUES
  (1, 'nl'), (1, 'de'), (1, 'be'), (1, 'fr'),
  (2, 'de'), (2, 'fr'), (2, 'be'),
  (3, 'fr'), (3, 'nl'),
  (4, 'nl')

然后你将有这个单一的查询......

SELECT
  map.country,
  COUNT(*)
FROM
  demo
INNER JOIN
  map
    ON map.demo_id = demo.id
WHERE
      demo.field_a = 'xzx'
  AND demo.field_b = 'bbb'

答案 1 :(得分:1)

select a.country,count(*) from
(
select 'be' as country
union all
select 'de' as country
union all
select 'fr' as country
union all
select 'nl' as country
)a join demo d
on d.destination like '%'+a.country+'%'
AND d.field_a=xzx AND d.field_b=bbb
group by a.country

我不确定mySQL是否支持派生表。如果不支持,则必须创建包含所有不同国家/地区值的临时表,并将其替换为上述查询中的表a

答案 2 :(得分:0)

使用COUNT CASE WHEN ... THEN ... END

SELECT 
COUNT(CASE WHEN destination LIKE "%be%" THEN 1 ELSE NULL END) AS "BE",
COUNT(CASE WHEN destination LIKE "%fr%" THEN 1 ELSE NULL END) AS "FR",
COUNT(CASE WHEN destination LIKE "%de%" THEN 1 ELSE NULL END) AS "DE",
COUNT(CASE WHEN destination LIKE "%nl%" THEN 1 ELSE NULL END) AS "NL"
FROM demo
WHERE field_a = "xzx" AND field_b = "bbb"

但你应该考虑改变你桌子的结构。实际上并没有建议在单个字段中使用逗号分隔值。

相反,你应该在这里有一个每个旅行的ID(或者不管它是什么,我说旅行因为目的地字段)。然后,为此旅行中的每个目的地创建一个条目。有了这种结构,你就会有这样的请求:

SELECT destination, COUNT(id) 
FROM demo 
WHERE field_a = "xzx" AND field_b = "bbb" 
GROUP BY destination