Requests Table:
requests
+id (INT) AUTO_INCREMENT
+title (VARCHAR)
Statuses Table:
statuses
+id (INT) AUTO_INCREMENT
+title (VARCHAR)
Relationship Table:
request_status (MANY TO MANY)
+id (INT) AUTO_INCREMENT
+request_id (INT) Foreign Key
+status_id (INT)
I want to count only those requests whose current status_id is 2 . Current Request's Status (status_id) is the last one in the request_status table.
What will be the perfect high-performance query if data is around 1600k
Assuming that the latest status is the one with greatest id:
SELECT COUNT(*)
FROM request_status
WHERE status_id = 2
AND NOT EXISTS (
SELECT 1
FROM request_status AS x
WHERE request_id = request_status.request_id
AND id > request_status.id
)
Or this:
SELECT COUNT(*)
FROM (
SELECT 1
FROM request_status
GROUP BY request_id
HAVING MAX(CASE WHEN status_id = 2 THEN id END) = MAX(id)
) AS x
You will need some indexes. I suggest creating these ones:
KEY ix1 (request_id, status_id)
KEY ix2 (status_id, request_id)
SELECT COUNT(*) FROM request_status WHERE status_id = 2;
如果我正确理解了您的问题,该方法应该最好地工作-即计算status_id等于2的对。
The schema for the relation table has several inefficiencies. I discuss them here .
But, instead, lets change the schema to make it even more efficient. Instead of 3 tables with a many:many mapping, have just one table:
CREATE TABLE requests (
id ...,
latest_status ENUM('eating', 'sleeping', 'running'),
all_statuses SET('eating', 'sleeping', 'running'),
) ENGINE=InnoDB;
(Alternatively, you could use TINYINTs
, but with different syntax.)
When the status for a given request
changes, set latest_status
and "or" the new status into all_statuses
.
To check for latest being running
: WHERE latest_status = 'running'
.
Or, if using some numeric value: WHERE latest_status = 2
.
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.