MySQL JOIN -> 从右侧获取所有数据 table 即使没有匹配
MySQL JOIN -> Get all data from right table even if there is no match
我有两个 tables,一个有 data (A) 另一个有 categories (B) 这是在这些类别之一或未分类。我需要做简单的统计,所以我使用 JOIN 从 table A 获取所有数据并将其与 table B.
我需要的是,即使 A 中没有匹配项,我也想在图表上显示 B 中的所有类别(计数 = 0,但我需要显示它们)。
因此,如果没有具有该类别 ID 的项目,它根本不会显示该类别,但我需要显示它,即使它有 0 个项目。
我尝试了 LEFT JOIN、RIGHT JOIN,它们都使用了 UNION,但没有任何效果。
Table一个
id | some | irrelevant | data | category
-----------------------------------------
1 | | | | 0
2 | | | | 0
3 | | | | 1
4 | | | | 2
5 | | | | 3
6 | | | | 3
. . . . . . . . . . .
Table B
id | title | color
---------------------
1 | Cat 1 | #FFFFFF
2 | Cat 2 | #FF00FF
3 | Cat 3 | #FF0000
4 | Cat 4 | #00FF00
5 | Cat 5 | #00FFFF
6 | Cat 6 | #000000
7 | Cat 7 | #FFFF00
有了这些数据,我想要得到类似的东西:
Array ( [category] => 0 [count] => 3 [title] => [color] => )
Array ( [category] => 1 [count] => 1 [title] => Cat 1 [color] => #FFFFFF )
Array ( [category] => 2 [count] => 1 [title] => Cat 2 [color] => #FF00FF )
Array ( [category] => 3 [count] => 2 [title] => Cat 3 [color] => #FF0000 )
Array ( [category] => 4 [count] => 0 [title] => Cat 4 [color] => #00FF00 )
Array ( [category] => 5 [count] => 0 [title] => Cat 5 [color] => #00FFFF )
Array ( [category] => 6 [count] => 0 [title] => Cat 6 [color] => #000000 )
Array ( [category] => 7 [count] => 0 [title] => Cat 7 [color] => #FFFF00 )
但这就是我实际上得到的:
Array ( [category] => 0 [count] => 3 [title] => [color] => )
Array ( [category] => 1 [count] => 1 [title] => Cat 1 [color] => #FFFFFF )
Array ( [category] => 2 [count] => 1 [title] => Cat 2 [color] => #FF00FF )
Array ( [category] => 3 [count] => 2 [title] => Cat 3 [color] => #FF0000 )
这是通话:
"SELECT category, COUNT(*) AS count, title, color FROM A LEFT JOIN B ON B.id=A.category GROUP BY category"
PS.: 再一次,我也实现了 RIGHT join 和 RIGHT 和 LEFT 的 UNION join。
此外,table 的名称非常长,不能像 A.category 等那样在调用中真正使用它们
有没有什么方法可以不使用两次 SQL 调用和两次循环来做到这一点?我真的不想那样做。
谢谢。
[更新]
添加创建数据 SQL 和下面的 SQL 查询来证明数据:
要添加测试数据 运行 以下 SQL 命令:
DROP TABLE junk_category;
CREATE TABLE junk_category (
id INT PRIMARY KEY,
name VARCHAR(32) NOT NULL
);
INSERT INTO junk_category (id,name) VALUES (1,'Cat 1'), (2,'Cat 2'), (3, 'Cat 3'), (4, 'Cat 4');
DROP TABLE junk_data;
CREATE TABLE junk_data (
id INT PRIMARY KEY,
name VARCHAR(32) NOT NULL,
category INT NULL,
INDEX byCategory (category)
);
INSERT INTO junk_data (id, name, category)
VALUES
(1,'one',1),
(2,'two',1),
(3,'three',1),
(4,'four',2),
(5,'five',2),
(6,'six',3),
(7,'seven',NULL),
(8,'eight',NULL);
查询测试数据:
SELECT 'Uncategorized' AS category, COUNT(*) AS count
FROM junk_data A
WHERE A.category IS NULL
UNION
SELECT B.name AS category, COUNT(DISTINCT A.id) AS count
FROM junk_category B
LEFT JOIN junk_data A ON A.category=B.id
GROUP BY category
与我之前给您的查询相比,唯一需要更改的是 DISTINCT A.id。我在之前的粘贴中错过了这一点。如果没有 DISTINCT A.id,类别本身计为 1。DISTINCT 将其限制为数据 table。但是,您说您看到的是 3...但是查询没有 "copy" 并且应该是 none 的地方也不是 3...所以如果您看到 3 的地方应该是是 none,还有一些其他问题。
[更新 2015-03-03]
如果您没有从此查询中获取所有类别:
SELECT B.name AS category, COUNT(DISTINCT A.id) AS count
FROM junk_category B
LEFT JOIN junk_data A ON A.category=B.id
GROUP BY category
这不会 return 您的所有类别的唯一原因是:如果它们没有唯一命名。上面唯一的过滤器是 GROUP BY
.
但是,我意识到我可能让您感到困惑,因为我将 B.name AS category
命名为您的其中一个专栏的名称。 GROUP BY
实际上是 GROUP BY B.name
。因此,丢失任何条目的唯一方法是它们具有相同的 B.name
。所以,无论如何,你的 GROUP BY
需要在你的 B table 上,而不是你的 A table.
如果不查看您的实际查询 并查看您的 GROUP BY 或 WHERE 是否设置了额外的限制,我将无能为力。或者利用我的安装垃圾 sql 并确保您可以获得相同的结果,然后尝试找出我的查询与您的实际查询之间的差异。
This answer is not the best variant, but I want to provide it in case
nobody here knows how to do what I want with single query and loop.
我 "solved" 知道它带有 while 循环(这正是我不想使用的),但实际上看起来我想要的是不可能的...
$get_stats = dbquery("SELECT COUNT(*) AS count, category FROM XXX GROUP BY category");
$get_cats = dbquery("SELECT * FROM YYYYY");
$categories = array();
$stats_arr = array();
while ($cat = dbarray($get_cats)){
$categories[$cat['id']] = array($cat['title'], $cat['color']);
$stats_arr[$cat['id']] = array('count' => 0, 'title' => $cat['title'], 'color' => $cat['color']);
}
while ($stats = dbarray($get_stats)){
if ($stats['category'] === "0"){
$stats_arr[0] = array('count' => $stats['count'], 'title' => 'Uncategorized', 'color' => '#FFFFFF');
}else{
$stats_arr[$stats['category']] = array('count' => $stats['count'], 'title' => $categories[$stats['category']][0], 'color' => $categories[$stats['category']][1]);
}
}
ksort($stats_arr);
foreach ($stats_arr as $id => $data) {
// Code here
}
我仍然想让它在不需要所有这些循环的情况下工作。
目前还可以,因为它在我已经循环遍历类别的页面上,但它仍然添加了 2 个循环,我想在单独的页面上使用它,所以我需要通过单个查询 + 循环来解决它.
那这个呢:
MySQL 5.5.32 架构设置:
CREATE TABLE TableA
(`id` int, `category` int)
;
INSERT INTO TableA
(`id`, `category`)
VALUES
(1, 0),
(2, 0),
(3, 1),
(4, 2),
(5, 3),
(6, 3)
;
CREATE TABLE TableB
(`id` int, `title` varchar(5), `color` varchar(7))
;
INSERT INTO TableB
(`id`, `title`, `color`)
VALUES
(1, 'Cat 1', '#FFFFFF'),
(2, 'Cat 2', '#FF00FF'),
(3, 'Cat 3', '#FF0000'),
(4, 'Cat 4', '#00FF00'),
(5, 'Cat 5', '#00FFFF'),
(6, 'Cat 6', '#000000'),
(7, 'Cat 7', '#FFFF00')
;
查询 1:
SELECT TableB.id as category, count(distinct TableA.id) as count,title,color
FROM
(SELECT * FROM TableB
UNION
SELECT 0 as id, '' as title, '' as color) AS TableB
LEFT OUTER JOIN TableA on TableB.id = TableA.category
GROUP BY TableB.id, title, color
ORDER BY TableB.id
| CATEGORY | COUNT | TITLE | COLOR |
|----------|-------|-------|---------|
| 0 | 2 | | |
| 1 | 1 | Cat 1 | #FFFFFF |
| 2 | 1 | Cat 2 | #FF00FF |
| 3 | 2 | Cat 3 | #FF0000 |
| 4 | 0 | Cat 4 | #00FF00 |
| 5 | 0 | Cat 5 | #00FFFF |
| 6 | 0 | Cat 6 | #000000 |
| 7 | 0 | Cat 7 | #FFFF00 |
此外,您可以在 TableB
中添加一个 ID 为 0 的类别,而不是使用 UNION SELECT 0 as id, '' as title, '' as color
我有两个 tables,一个有 data (A) 另一个有 categories (B) 这是在这些类别之一或未分类。我需要做简单的统计,所以我使用 JOIN 从 table A 获取所有数据并将其与 table B.
我需要的是,即使 A 中没有匹配项,我也想在图表上显示 B 中的所有类别(计数 = 0,但我需要显示它们)。
因此,如果没有具有该类别 ID 的项目,它根本不会显示该类别,但我需要显示它,即使它有 0 个项目。
我尝试了 LEFT JOIN、RIGHT JOIN,它们都使用了 UNION,但没有任何效果。
Table一个
id | some | irrelevant | data | category
-----------------------------------------
1 | | | | 0
2 | | | | 0
3 | | | | 1
4 | | | | 2
5 | | | | 3
6 | | | | 3
. . . . . . . . . . .
Table B
id | title | color
---------------------
1 | Cat 1 | #FFFFFF
2 | Cat 2 | #FF00FF
3 | Cat 3 | #FF0000
4 | Cat 4 | #00FF00
5 | Cat 5 | #00FFFF
6 | Cat 6 | #000000
7 | Cat 7 | #FFFF00
有了这些数据,我想要得到类似的东西:
Array ( [category] => 0 [count] => 3 [title] => [color] => )
Array ( [category] => 1 [count] => 1 [title] => Cat 1 [color] => #FFFFFF )
Array ( [category] => 2 [count] => 1 [title] => Cat 2 [color] => #FF00FF )
Array ( [category] => 3 [count] => 2 [title] => Cat 3 [color] => #FF0000 )
Array ( [category] => 4 [count] => 0 [title] => Cat 4 [color] => #00FF00 )
Array ( [category] => 5 [count] => 0 [title] => Cat 5 [color] => #00FFFF )
Array ( [category] => 6 [count] => 0 [title] => Cat 6 [color] => #000000 )
Array ( [category] => 7 [count] => 0 [title] => Cat 7 [color] => #FFFF00 )
但这就是我实际上得到的:
Array ( [category] => 0 [count] => 3 [title] => [color] => )
Array ( [category] => 1 [count] => 1 [title] => Cat 1 [color] => #FFFFFF )
Array ( [category] => 2 [count] => 1 [title] => Cat 2 [color] => #FF00FF )
Array ( [category] => 3 [count] => 2 [title] => Cat 3 [color] => #FF0000 )
这是通话:
"SELECT category, COUNT(*) AS count, title, color FROM A LEFT JOIN B ON B.id=A.category GROUP BY category"
PS.: 再一次,我也实现了 RIGHT join 和 RIGHT 和 LEFT 的 UNION join。 此外,table 的名称非常长,不能像 A.category 等那样在调用中真正使用它们
有没有什么方法可以不使用两次 SQL 调用和两次循环来做到这一点?我真的不想那样做。
谢谢。
[更新] 添加创建数据 SQL 和下面的 SQL 查询来证明数据:
要添加测试数据 运行 以下 SQL 命令:
DROP TABLE junk_category;
CREATE TABLE junk_category (
id INT PRIMARY KEY,
name VARCHAR(32) NOT NULL
);
INSERT INTO junk_category (id,name) VALUES (1,'Cat 1'), (2,'Cat 2'), (3, 'Cat 3'), (4, 'Cat 4');
DROP TABLE junk_data;
CREATE TABLE junk_data (
id INT PRIMARY KEY,
name VARCHAR(32) NOT NULL,
category INT NULL,
INDEX byCategory (category)
);
INSERT INTO junk_data (id, name, category)
VALUES
(1,'one',1),
(2,'two',1),
(3,'three',1),
(4,'four',2),
(5,'five',2),
(6,'six',3),
(7,'seven',NULL),
(8,'eight',NULL);
查询测试数据:
SELECT 'Uncategorized' AS category, COUNT(*) AS count
FROM junk_data A
WHERE A.category IS NULL
UNION
SELECT B.name AS category, COUNT(DISTINCT A.id) AS count
FROM junk_category B
LEFT JOIN junk_data A ON A.category=B.id
GROUP BY category
与我之前给您的查询相比,唯一需要更改的是 DISTINCT A.id。我在之前的粘贴中错过了这一点。如果没有 DISTINCT A.id,类别本身计为 1。DISTINCT 将其限制为数据 table。但是,您说您看到的是 3...但是查询没有 "copy" 并且应该是 none 的地方也不是 3...所以如果您看到 3 的地方应该是是 none,还有一些其他问题。
[更新 2015-03-03]
如果您没有从此查询中获取所有类别:
SELECT B.name AS category, COUNT(DISTINCT A.id) AS count
FROM junk_category B
LEFT JOIN junk_data A ON A.category=B.id
GROUP BY category
这不会 return 您的所有类别的唯一原因是:如果它们没有唯一命名。上面唯一的过滤器是 GROUP BY
.
但是,我意识到我可能让您感到困惑,因为我将 B.name AS category
命名为您的其中一个专栏的名称。 GROUP BY
实际上是 GROUP BY B.name
。因此,丢失任何条目的唯一方法是它们具有相同的 B.name
。所以,无论如何,你的 GROUP BY
需要在你的 B table 上,而不是你的 A table.
如果不查看您的实际查询 并查看您的 GROUP BY 或 WHERE 是否设置了额外的限制,我将无能为力。或者利用我的安装垃圾 sql 并确保您可以获得相同的结果,然后尝试找出我的查询与您的实际查询之间的差异。
This answer is not the best variant, but I want to provide it in case nobody here knows how to do what I want with single query and loop.
我 "solved" 知道它带有 while 循环(这正是我不想使用的),但实际上看起来我想要的是不可能的...
$get_stats = dbquery("SELECT COUNT(*) AS count, category FROM XXX GROUP BY category");
$get_cats = dbquery("SELECT * FROM YYYYY");
$categories = array();
$stats_arr = array();
while ($cat = dbarray($get_cats)){
$categories[$cat['id']] = array($cat['title'], $cat['color']);
$stats_arr[$cat['id']] = array('count' => 0, 'title' => $cat['title'], 'color' => $cat['color']);
}
while ($stats = dbarray($get_stats)){
if ($stats['category'] === "0"){
$stats_arr[0] = array('count' => $stats['count'], 'title' => 'Uncategorized', 'color' => '#FFFFFF');
}else{
$stats_arr[$stats['category']] = array('count' => $stats['count'], 'title' => $categories[$stats['category']][0], 'color' => $categories[$stats['category']][1]);
}
}
ksort($stats_arr);
foreach ($stats_arr as $id => $data) {
// Code here
}
我仍然想让它在不需要所有这些循环的情况下工作。
目前还可以,因为它在我已经循环遍历类别的页面上,但它仍然添加了 2 个循环,我想在单独的页面上使用它,所以我需要通过单个查询 + 循环来解决它.
那这个呢:
MySQL 5.5.32 架构设置:
CREATE TABLE TableA
(`id` int, `category` int)
;
INSERT INTO TableA
(`id`, `category`)
VALUES
(1, 0),
(2, 0),
(3, 1),
(4, 2),
(5, 3),
(6, 3)
;
CREATE TABLE TableB
(`id` int, `title` varchar(5), `color` varchar(7))
;
INSERT INTO TableB
(`id`, `title`, `color`)
VALUES
(1, 'Cat 1', '#FFFFFF'),
(2, 'Cat 2', '#FF00FF'),
(3, 'Cat 3', '#FF0000'),
(4, 'Cat 4', '#00FF00'),
(5, 'Cat 5', '#00FFFF'),
(6, 'Cat 6', '#000000'),
(7, 'Cat 7', '#FFFF00')
;
查询 1:
SELECT TableB.id as category, count(distinct TableA.id) as count,title,color
FROM
(SELECT * FROM TableB
UNION
SELECT 0 as id, '' as title, '' as color) AS TableB
LEFT OUTER JOIN TableA on TableB.id = TableA.category
GROUP BY TableB.id, title, color
ORDER BY TableB.id
| CATEGORY | COUNT | TITLE | COLOR |
|----------|-------|-------|---------|
| 0 | 2 | | |
| 1 | 1 | Cat 1 | #FFFFFF |
| 2 | 1 | Cat 2 | #FF00FF |
| 3 | 2 | Cat 3 | #FF0000 |
| 4 | 0 | Cat 4 | #00FF00 |
| 5 | 0 | Cat 5 | #00FFFF |
| 6 | 0 | Cat 6 | #000000 |
| 7 | 0 | Cat 7 | #FFFF00 |
此外,您可以在 TableB
中添加一个 ID 为 0 的类别,而不是使用UNION SELECT 0 as id, '' as title, '' as color