0

我有一张这样的桌子:

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

Wheremondaytuesday是 SET 类型的列。每个数字代表一周中给定日期的可用小时数。我想计算每小时可用的条目数,以便查看大多数受访者何时空闲。

例如, on monday, 3 的计数为 2,for tuesday,3 的计数为 1。我想使用尽可能少的查询。

我已经为此工作了几个小时,但无法弄清楚。任何帮助,将不胜感激!关于如何更好地做到这一点的建议也将不胜感激!谢谢!!

4

1 回答 1

0

正如@PRPGFerret 建议的那样,您确实应该规范化您的架构(请参阅@BillKarwin 对“在数据库列中存储逗号分隔列表真的那么糟糕吗?的回答):

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上查看。

请注意,正如@ArielChelsău 所观察到的,星期二的计数1不是0问题中提到的。

于 2012-12-15T11:07:21.013 回答