簡體   English   中英

當第二個子表有記錄時,如何通過父表字段對子表的字段求和?

[英]How to sum a field of a child table by a parent table field when a second child table has records?

給定以下三個示例表:

錦標賽_oc

ID_
1
2

match_oc:

ID_ 錦標賽_oc_id
1 1
2 1

stat_oc

ID_ 錦標賽_oc_id 價值_
1 1 1
2 1 1
3 2 1

如果給定的tournament_oc.id_ oc.id_ 有一個或多個match_oc記錄,我想將stat_oc.value_tournament_oc.id_ oc.id_ 相加。 在這種情況下,所需的輸出應該是:

錦標賽_oc_id sum_value
1 2

我試過了:

SELECT
    t.id_ AS tournament_oc_id, sum(s.value_) AS sum_value
FROM
    tournament_oc AS t
        JOIN
    match_oc AS m ON m.tournament_oc_id = t.id_
        JOIN
    stat_oc as s on s.tournament_oc_id = t.id_
GROUP BY t.id_

但是,這會返回:

錦標賽_oc_id sum_value
1 4

大概是因為有兩條match_oc記錄,其中tournament_oc.id_ oc.id_ == 1。

我將如何達到預期的結果?

用於復制表的 SQL:

CREATE DATABASE  IF NOT EXISTS `test` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `test`;

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

DROP TABLE IF EXISTS `match_oc`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `match_oc` (
  `id_` int NOT NULL AUTO_INCREMENT,
  `tournament_oc_id` int NOT NULL,
  PRIMARY KEY (`id_`),
  KEY `fk__match_oc__tournament_oc_id_idx` (`tournament_oc_id`),
  CONSTRAINT `fk__match_oc__tournament_oc_id` FOREIGN KEY (`tournament_oc_id`) REFERENCES `tournament_oc` (`id_`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

LOCK TABLES `match_oc` WRITE;
/*!40000 ALTER TABLE `match_oc` DISABLE KEYS */;
INSERT INTO `match_oc` VALUES (1,1),(2,1);
/*!40000 ALTER TABLE `match_oc` ENABLE KEYS */;
UNLOCK TABLES;

DROP TABLE IF EXISTS `stat_oc`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `stat_oc` (
  `id_` int NOT NULL AUTO_INCREMENT,
  `tournament_oc_id` int NOT NULL,
  `value_` tinyint DEFAULT NULL,
  PRIMARY KEY (`id_`),
  KEY `fk__stat_oc__tournament_oc_id_idx` (`tournament_oc_id`),
  CONSTRAINT `fk__stat_oc__tournament_oc_id` FOREIGN KEY (`tournament_oc_id`) REFERENCES `tournament_oc` (`id_`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

LOCK TABLES `stat_oc` WRITE;
/*!40000 ALTER TABLE `stat_oc` DISABLE KEYS */;
INSERT INTO `stat_oc` VALUES (1,1,1),(2,1,1),(3,2,1);
/*!40000 ALTER TABLE `stat_oc` ENABLE KEYS */;
UNLOCK TABLES;

DROP TABLE IF EXISTS `tournament_oc`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `tournament_oc` (
  `id_` int NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id_`)
) ENGINE=InnoDB AUTO_INCREMENT=26193 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

LOCK TABLES `tournament_oc` WRITE;
/*!40000 ALTER TABLE `tournament_oc` DISABLE KEYS */;
INSERT INTO `tournament_oc` VALUES (1),(2);
/*!40000 ALTER TABLE `tournament_oc` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

您不能在JOIN操作的同一級別上進行聚合,只要在聚合之前執行此操作即可,因此,如果錦標賽在多場比賽中進行了比賽,您將獲得每場比賽的重復總和(在你的情況,2匹配2 = 4)。

為了規避這個問題,你可以先過濾掉沒有匹配的錦標賽(在WHERE子句中),然后總結你的錦標賽。

SELECT tournament_oc_id,
       SUM(value_)         AS sum_value
FROM stat_oc
WHERE tournament_oc_id IN (SELECT tournament_oc_id FROM match_oc) 
GROUP BY tournament_oc_id

只要假設如果錦標賽不存在,它也不應該出現在“ match_oc ”表中,就沒有必要使用“ tournament_oc ”表。

此處查看演示。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM