我有一张这样的表:
+----+-----------+---------+
| ID | monday | tuesday |
+---+-----------+----------+
| 1 | 1,2,3,4,5 | 3,4,5,6 |
| 2 | 3,4,5 | 5,6,7 |
+----+-----------+---------+
其中monday
和tuesday
是SET类型列。每个数字代表一周中给定日期的一小时可用性。我想计算每小时可用的条目数,这样我就可以看到大多数受访者都是免费的。
例如,在monday
上,3的计数为2;对于tuesday
,3的计数为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
。