วิธี JOIN 2 ตารางและนับจำนวนที่ตารางแรก???
ผมมีตารางที่ 1 คือ users มีจำนวนทั้งหมด 142 แต่ถ้าใส่เงื่อนไข WHERE user_deleted = 0 จะเหลือ 139
Code (SQL)
CREATE TABLE IF NOT EXISTS `rdb_users` (
`user_id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_login` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'username (must be unique for use as login)',
`user_email` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'email (must be unique for use as login)',
`user_password` text COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'password',
`user_display_name` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'display name for cloak the username',
`user_create` datetime DEFAULT NULL COMMENT 'user created date/time',
`user_create_gmt` datetime DEFAULT NULL COMMENT 'user created date/time in gmt 0',
`user_lastupdate` datetime NOT NULL DEFAULT current_timestamp() COMMENT 'user last update',
`user_lastupdate_gmt` datetime NOT NULL DEFAULT current_timestamp() COMMENT 'user last update in gmt 0',
`user_lastlogin` datetime DEFAULT NULL COMMENT 'user last login',
`user_lastlogin_gmt` datetime DEFAULT NULL COMMENT 'user last login in gmt 0',
`user_status` int(1) NOT NULL DEFAULT 0 COMMENT 'user status. 0=disabled, 1=enabled',
`user_statustext` varchar(191) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'user status text for describe what happens. (untranslated.)',
`user_deleted` int(1) NOT NULL DEFAULT 0 COMMENT 'user soft deleted. 0=not deleted, 1=deleted',
`user_deleted_since` datetime DEFAULT NULL COMMENT 'user deleted since date/time',
`user_deleted_since_gmt` datetime DEFAULT NULL COMMENT 'user deleted since date/time in gmt 0',
PRIMARY KEY (`user_id`),
UNIQUE KEY `user_login` (`user_login`),
UNIQUE KEY `user_email` (`user_email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci ROW_FORMAT=DYNAMIC COMMENT='contain users account' AUTO_INCREMENT=142 ;
-----------------------
ตารางที่ 2 คือ users_roles มีคอลัมน์ user_id ที่ค่าไม่สัมพันธ์กับตาราง users คือมี user อยู่แต่จะไม่มี role เลยก็ได้
Code (SQL)
CREATE TABLE IF NOT EXISTS `rdb_users_roles` (
`usersroles_id` bigint(20) NOT NULL AUTO_INCREMENT,
`user_id` bigint(20) NOT NULL COMMENT 'refer to users.user_id',
`userrole_id` bigint(20) NOT NULL COMMENT 'refer to user_roles.userrole_id',
PRIMARY KEY (`usersroles_id`),
KEY `user_id` (`user_id`),
KEY `userrole_id` (`userrole_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='contain user''s roles relation' AUTO_INCREMENT=70 ;
----------------------
ทีนี้ต้องการนับจำนวนผู้ใช้จากตารางแรกเป็นหลัก
Code (SQL)
SELECT
COUNT(`users`.`user_id`) AS `total`
FROM `rdb_users` AS `users`
LEFT JOIN `rdb_users_roles` AS `users_roles`
ON `users_roles`.`user_id` = `users`.`user_id`
WHERE 1
AND `user_deleted` = 0
ผลลัพธ์ที่ได้จะเป็น 142 ทั้งที่ควรจะเป็น 139
อันนี้ผลลัพธ์ที่ได้ไม่ตรง ควรใช้คำสั่งอย่างไรดีครับ?
แต่ถ้าใส่เงื่อนไขเข้าไป เช่น ผู้ดูแลกรองหน้าที่ userrole_id = 3 ถ้าไม่มีเงื่อนไข user_deleted = 0 จะมีทั้งหมด 15 แต่เงื่อนไข user_deleted = 0 ต้องใส่ มันจึงเหลือ 12 ซึ่งกรณีนี้ดันนับถูก
Code (SQL)
SELECT
COUNT(`users`.`user_id`) AS `total`
FROM `rdb_users` AS `users`
LEFT JOIN `rdb_users_roles` AS `users_roles`
ON `users_roles`.`user_id` = `users`.`user_id`
WHERE 1
AND `user_deleted` = 0
AND `users_roles`.`userrole_id` = 3
ข้างบนนี้ ถ้าไม่มี deleted = 0 จะต้องเป็น 15 แต่มันต้องมีเลยนับได้ 12 ซึ่งตรงเป๊ะ
แต่ถ้าไม่กรอง userrole_id เลยดันนับไม่ตรง ทำยังไงให้ไม่กรอง userrole_id แล้วนับได้ตรงครับ?Tag : PHP, MySQL, MySQL
Date :
2019-10-20 15:44:44
By :
mr.v
View :
903
Reply :
5
group สิครับ
Date :
2019-10-20 15:56:06
By :
mongkon.k
group ไม่ได้ครับ มันจะไม่นับออกมาว่าเท่าไหร่แต่จะออกมาเป็น 1 1 1 1 ตามจำนวน users เลยซึ่งกิน memory มากกว่า
Date :
2019-10-20 15:57:56
By :
mr.v
Query แรกไม่ต้อง join ครับ เพราะต้องการนับจำนวนผู้ใช้จากตารางแรก
Date :
2019-10-21 11:16:02
By :
birdbird27
ถ้าไม่ join มันจะใช้เงื่อนไข AND `users_roles`.`userrole_id` = 3 ไม่ได้ครับ และตัว WHERE ตัวนี้มันค่อนข้าง dynamic คือแล้วแต่ผู้ใช้จะกรอง ดังนั้น LEFT JOIN มันต้องมีเผื่อไว้ดักรอเลย
ตอนนี้ผมใช้ COUNT(DISTINCT `users`.`user_id`) แทน
ประวัติการแก้ไข 2019-10-21 18:15:15
Date :
2019-10-21 18:14:44
By :
mr.v
Load balance : Server 03