If I know how to filter by all signs of the zodiac, then by the sign of the zodiac 'Capricorn' (from December 22 to January 20) I do not know how to select.
Here is the structure of the tables, do I need to select all users with the sign of the zodiac 'Capricorn'?
The structure of the tables can be changed (or even add new tables if required):
CREATE TABLE IF NOT EXISTS `horoscope` (
`id` INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL UNIQUE,
`date_start` VARCHAR(5),
`date_end` VARCHAR(5)
);
CREATE INDEX `horoscope_idx_1` ON `horoscope`(`date_start`, `date_end`);
CREATE TABLE IF NOT EXISTS `user` (
`id` INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
`name` VARCHAR(255) NOT NULL,
`birthday` DATE NOT NULL
);
Insert test data
# Insert horoscope in table
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Aries', '03-21', '04-20');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Taurus', '04-21', '05-20');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Gemini', '05-22', '06-21');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Cancer', '06-22', '07-22');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Leo', '07-23', '08-23');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Virgin', '08-24', '09-22');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Libra', '08-23', '10-22');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Scorpio', '10-23', '11-21');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Sagittarius', '11-22', '12-21');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Capricorn', '12-22', '01-20');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Aquarius', '01-21', '02-19');
INSERT INTO `horoscope` (`name`, `date_start`, `date_end`) VALUES ('Pisces', '02-20', '03-20');
# Insert random user in table
DROP PROCEDURE IF EXISTS `add_user`;
CREATE PROCEDURE `add_user`(IN `count_user` INT)
LANGUAGE SQL
DETERMINISTIC
SQL SECURITY DEFINER
COMMENT 'A procedure for inserting random user'
BEGIN
DECLARE i INT DEFAULT (
SELECT `id`
FROM `user`
ORDER BY `id` DESC
LIMIT 1
);
IF i IS NULL
THEN SET i = 1;
END IF;
SET `count_user` = `count_user` + i;
WHILE i <= `count_user` DO
SET @`name` = CONCAT('user_', i);
SET @`user_birth` = '1980-01-01' + INTERVAL (RAND() * 365 * 20) DAY;
INSERT INTO `user` (`name`, `birthday`) VALUES (@`name`, @`user_birth`);
SET i = i + 1;
END WHILE;
END;
CALL `add_user`(1000);
DROP PROCEDURE IF EXISTS `add_user`;
I decided =)
SELECT *
FROM user as u
WHERE (
DATE_FORMAT(u.birthday, '%m%d') >= (
SELECT
CONCAT(LEFT(`h`.`date_start`, 2), RIGHT(`h`.`date_start`, 2))
FROM horoscope h
WHERE h.name = 'Capricorn'
) AND DATE_FORMAT(u.birthday, '%m%d') <= 1231
) OR (
DATE_FORMAT(u.birthday, '%m%d') >= 101 AND DATE_FORMAT(u.birthday, '%m%d') <= (
SELECT
CONCAT(LEFT(`h`.`date_end`, 2), RIGHT(`h`.`date_end`, 2))
FROM horoscope h
WHERE h.name = 'Capricorn'
)
);
If the boundaries of each zodiac sign are fixed dates, then it would make sense to add birth-sign as an attribute to each user instead of filtering by dates each and every time you need that information.
However I would suggest the following if you do need to filter:
select *
from user u
inner join horoscope h
where (h.date_start > h.date_end
and u.birthday between str_to_date(concat(year(u.birthday)-1, h.date_start),'%Y%m-%d')
and str_to_date(concat(year(u.birthday), h.date_end),'%Y%m-%d')
)
or (h.date_start < h.date_end
and u.birthday between str_to_date(concat(year(u.birthday), h.date_start),'%Y%m-%d')
and str_to_date(concat(year(u.birthday), h.date_end),'%Y%m-%d')
)
Note however that the indexing of the 2 varchar(5) columns in horoscope probably isn't going to be helpful to your queries.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.