计算Set类型中成员的出现次数

时间:2012-12-15 09:46:32

标签: mysql

我有一张这样的表:

  +----+-----------+---------+
  | ID | monday    | tuesday | 
  +---+-----------+----------+
  |  1 | 1,2,3,4,5 | 3,4,5,6 |
  |  2 | 3,4,5     | 5,6,7   |
  +----+-----------+---------+

其中mondaytuesday是SET类型列。每个数字代表一周中给定日期的一小时可用性。我想计算每小时可用的条目数,这样我就可以看到大多数受访者都是免费的。

例如,在monday上,3的计数为2;对于tuesday,3的计数为1.我想尽可能少地使用查询。

我已经在这个问题上工作了好几个小时,但无法理解。任何帮助,将不胜感激!关于如何做得更好的建议也将不胜感激!谢谢!

1 个答案:

答案 0 :(得分:0)

作为@PRPGFerret suggests,您确实应该规范化您的架构(请参阅@BillKarwin's answer to "Is storing a comma separated list in a database column really that bad?"):

CREATE TABLE Hours (Hour TINYINT UNSIGNED NOT NULL);
INSERT INTO Hours (Hour) VALUES
  ( 0),( 1),( 2),( 3),( 4),( 5),( 6),( 7),( 8),( 9),(10),(11),
  (12),(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23)
;

CREATE TABLE HoursAvailable (
  Day  ENUM(
         'Monday',
         'Tuesday',
         'Wednesday',
         'Thursday',
         'Friday',
         'Saturday',
         'Sunday'
       ) NOT NULL,
  ID   BIGINT  UNSIGNED NOT NULL,
  Hour TINYINT UNSIGNED NOT NULL,
  PRIMARY KEY (Hour, Day, ID)
);

INSERT INTO HoursAvailable (Day, ID, Hour)
  SELECT 'Monday', ID, Hour
  FROM   my_table JOIN Hours ON FIND_IN_SET(Hours.Hour, my_table.monday)
UNION ALL
  SELECT 'Tuesday', ID, Hour
  FROM   my_table JOIN Hours ON FIND_IN_SET(Hours.Hour, my_table.tuesday)
;

DROP TABLE Hours;
DROP TABLE my_table;

然后你可以这样做:

SELECT Day, COUNT(*) FROM HoursAvailable WHERE Hour = 3 GROUP BY Day;

sqlfiddle上查看。

如果不以这种方式规范化数据,您可能会做一些相当低效的事情:

SELECT SUM(FIND_IN_SET(3, monday )>0),
       SUM(FIND_IN_SET(3, tuesday)>0)
FROM   my_table;

sqlfiddle上查看。

请注意,与observed by @ArielChelsău一样,星期二的计数为1,而不是问题中提到的0