我遇到了“不是GROUP BY表达式”错误。
我需要搜索类似的标题,媒介和描述。 艺术家表由artistid,艺术家姓氏和艺术家名字组成。 工作表由workid,title,medium,description,artistid组成 artistid是独一无二的关键。
列出数据库中记录了多个副本的任何艺术作品的详细信息。
SELECT W.workid, W.title, W.medium, W.description, W.artistid, A.FirstName, A.LastName
FROM dtoohey.work W, dtoohey.artist A
GROUP BY W.artistid, A.FirstName, A.LastName
having count(*) > 1;
答案 0 :(得分:1)
似乎表格之间没有正确的连接(我建议一个......你应该做正确的连接)
如果你想在W.artistIid上使用该组(别名是每个艺术家的工作数的计数),你就不能选择W.workid,W.title,W.medium
SELECT W.artistid, A.FirstName, A.LastName
FROM dtoohey.work W
INNER JOIN dtoohey.artist A ON A.artistid = W.artistid
GROUP BY W.artistid, A.FirstName, A.LastName
having count(*) > 1;
否则,如果你想检查select是否为列选择返回多一行,你必须将所有列添加到group by子句
SELECT W.workid, W.title, W.medium, W.description, W.artistid, A.FirstName, A.LastName
FROM dtoohey.work W
INNER JOIN dtoohey.artist A ON A.artistid = W.artistid
GROUP BY W.workid, W.title, W.medium, W.description, W.artistid, A.FirstName, A.LastName
having count(*) > 1;
答案 1 :(得分:1)
也许写一个答案(专注于@ mathguy对缺失连接特性的观察,以及SELECT列与GROUP BY / HAVING的组合不适合的那个)更好地找出你的问题并提出想法如何提高问题;-) ...下次我建议在这个问题上更加沉重,所以世界不必在答案上如此沉重。
我认为这不是MySQL,Oracle,或者不是数据库特定的问题,而是更多的SQL初学者学习之旅......您可能还希望在此处查找联接解释:"Difference between Inner Join & Full join"
从相关信息的最小子集开始:2个表格艺术家和与共享ID相关的工作(比如artist_id)。
直接在PostgreSQL或ParStream等数据库中遇到麻烦的一件事是通过查询既不按分组也不按聚合/过滤来选择组中的列。但是我们走了:
创建表格:
$psql> CREATE TABLE artist(artist_id INT, given_name VARCHAR(42), family_name VARCHAR(99));
CREATE TABLE
$psql> CREATE TABLE work(work_id INT, artist_id INT, title VARCHAR(42));
CREATE TABLE
插入一些数据:
$psql> INSERT INTO artist VALUES(1, 'John', 'Doe');
INSERT 0 1
$psql> INSERT INTO artist VALUES(2, 'Natalie', 'Noir');
INSERT 0 1
$psql> INSERT INTO work VALUES(43, 1, 'The game is on');
INSERT 0 1
$psql> INSERT INTO work VALUES(44, 1, 'The game is over');
INSERT 0 1
$psql> INSERT INTO work VALUES(98, 2, 'La nuit commonce');
INSERT 0 1
$psql> INSERT INTO work VALUES(97, 2, 'Un jour se lve');
INSERT 0 1
检查其中的内容:
$psql> SELECT * FROM work;
work_id | artist_id | title
---------+-----------+------------------
43 | 1 | The game is on
44 | 1 | The game is over
98 | 2 | La nuit commonce
97 | 2 | Un jour se lve
(4 rows)
$psql> SELECT * FROM artist;
artist_id | given_name | family_name
-----------+------------+-------------
1 | John | Doe
2 | Natalie | Noir
(2 rows)
显示隐含的INNER JOIN:
$psql> SELECT * FROM work W, artist A;
work_id | artist_id | title | artist_id | given_name | family_name
---------+-----------+------------------+-----------+------------+-------------
43 | 1 | The game is on | 1 | John | Doe
43 | 1 | The game is on | 2 | Natalie | Noir
44 | 1 | The game is over | 1 | John | Doe
44 | 1 | The game is over | 2 | Natalie | Noir
98 | 2 | La nuit commonce | 1 | John | Doe
98 | 2 | La nuit commonce | 2 | Natalie | Noir
97 | 2 | Un jour se lve | 1 | John | Doe
97 | 2 | Un jour se lve | 2 | Natalie | Noir
(8 rows)
显示带有虚拟条件的显式INNER JOIN,让解析器通过我们的查询(更新:不要在家中使用它,只显示混搭。):
$psql> SELECT * FROM work W INNER JOIN artist A ON 1 = 1;
work_id | artist_id | title | artist_id | given_name | family_name
---------+-----------+------------------+-----------+------------+-------------
43 | 1 | The game is on | 1 | John | Doe
43 | 1 | The game is on | 2 | Natalie | Noir
44 | 1 | The game is over | 1 | John | Doe
44 | 1 | The game is over | 2 | Natalie | Noir
98 | 2 | La nuit commonce | 1 | John | Doe
98 | 2 | La nuit commonce | 2 | Natalie | Noir
97 | 2 | Un jour se lve | 1 | John | Doe
97 | 2 | Un jour se lve | 2 | Natalie | Noir
(8 rows)
现在更有用的INNER JOIN只匹配两个表中的这些条目,这些条目通过“创建者”关系相关:
$psql> SELECT * FROM work W INNER JOIN artist A ON W.artist_id = A.artist_id;
work_id | artist_id | title | artist_id | given_name | family_name
---------+-----------+------------------+-----------+------------+-------------
43 | 1 | The game is on | 1 | John | Doe
44 | 1 | The game is over | 1 | John | Doe
98 | 2 | La nuit commonce | 2 | Natalie | Noir
97 | 2 | Un jour se lve | 2 | Natalie | Noir
(4 rows)
因此,我们盲目地相信数据管理部分总是正确地神奇地输入artist_id值并匹配我们的期望(在现实生活中,REFERENCES外键约束肯定会放在工作表中的列上(没有艺术家/创作者的工作)将决定艺术家的桌子成为“第一”因果关系。
上面你还看到从表格列表中选择与没有任何约束的INNER JOIN相同,即表格中所有条目的笛卡尔积与表艺术家的所有条目一起工作。
现在你的查询(为最小的表模型编辑了一点)除了我的请求想法中不清楚,错误输出如本答案文本顶部所述:
$psql> SELECT W.work_id, W.title, W.artist_id, A.given_name, A.family_name FROM work W, artist A GROUP BY W.artist_id, A.given_name, A.family_name HAVING COUNT(*) > 1;
ERROR: column "w.work_id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT W.work_id, W.title, W.artist_id, A.given_name, A.fam...
这当然不能通过使用更有意义的连接输入集(claro,因为错误指向select和group by list中的不匹配来解决这个问题:
$psql> SELECT W.work_id, W.title, W.artist_id, A.given_name, A.family_name FROM work W INNER JOIN artist A ON W.artist_id = A.artist_id GROUP BY W.artist_id, A.given_name, A.family_name HAVING COUNT(*) > 1;
ERROR: column "w.work_id" must appear in the GROUP BY clause or be used in an aggregate function
LINE 1: SELECT W.work_id, W.title, W.artist_id, A.given_name, A.fam...
您需要建议输入您想要获得的答案(工作)。在你这样做之前,这里有一些产品:
鉴于你只加入现有的artis和work id,你不需要那个having子句,因为既不是现有的艺术家也不是缺失的作品,也不会缺少艺术家和作品的组合将进入你的查询所依据的行集,所以:
$psql> SELECT title, R.* FROM ( SELECT W.work_id AS work_id_filtered, W.artist_id, A.given_name, A.family_name FROM work W INNER JOIN artist A ON W.artist_id = A.artist_id GROUP BY W.work_id, W.artist_id, A.given_name, A.family_name) R INNER JOIN work WW ON WW.work_id = R.work_id_filtered;
title | work_id_filtered | artist_id | given_name | family_name
------------------+------------------+-----------+------------+-------------
The game is on | 43 | 1 | John | Doe
The game is over | 44 | 1 | John | Doe
La nuit commonce | 98 | 2 | Natalie | Noir
Un jour se lve | 97 | 2 | Natalie | Noir
(4 rows)
这应该会让你有点笨拙,但是对于我的星期天早上来说,所有标题(非分组文件)的精彩列表与内部查询中的分组字段相结合就足够了。格式化查询可能写为:
SELECT title,
R.*
FROM
(SELECT W.work_id AS work_id_filtered,
W.artist_id,
A.given_name,
A.family_name
FROM
work W
INNER JOIN artist A ON W.artist_id = A.artist_id
GROUP BY W.work_id,
W.artist_id,
A.given_name,
A.family_name) R
INNER JOIN
work WW ON WW.work_id = R.work_id_filtered;
删除任何GROUP BY(直到问题提供有关该任务所需的详细信息):
$psql> SELECT W.work_id, W.title, W.artist_id, A.given_name, A.family_name FROM work W INNER JOIN artist A ON W.artist_id = A.artist_id;
work_id | title | artist_id | given_name | family_name
---------+------------------+-----------+------------+-------------
43 | The game is on | 1 | John | Doe
44 | The game is over | 1 | John | Doe
98 | La nuit commonce | 2 | Natalie | Noir
97 | Un jour se lve | 2 | Natalie | Noir
(4 rows)
格式化的查询不必水平滚动:
SELECT W.work_id, W.title, W.artist_id, A.given_name, A.family_name
FROM work W INNER JOIN artist A ON W.artist_id = A.artist_id;
注意:是的,正如@ThorstenKettner正确指出的那样,我编写了“全内加”这个词,我笑了,抱歉。也许我的大脑需要笛卡尔填充以平衡LEFT | RIGHT | FULL OUTER JOINs - 谁知道;-)
答案 2 :(得分:0)
我使用了scaisEdge回答并进行了编辑。我意识到如果我选择workid(唯一键),我将无法显示任何内容,但没有它,我的所有领域都已启动。
答案 3 :(得分:0)
正如已经提到的,问题主要是你还没有完全理解你在做什么。
第一点是你的加入。通过仅使用逗号分隔表,您使用的语法在二十多年前就变得多余了。作为初学者,你似乎很少使用它。你必须在一本非常古老的书或教程中找到它。简而言之:不要像这样加入表格。使用显式连接。逗号表示CROSS JOIN
。所以你拥有的是:
FROM dtoohey.work W CROSS JOIN dtoohey.artist A
这意味着您将每位艺术家与每件作品相结合。这很可能不是你想要的。您想加入相关的艺术家和作品。您的查询显示工作表中有artistid
,因此您的模型中有一位艺术家制作了一件作品。因此,适当的连接将是:
FROM dtoohey.work w
INNER JOIN dtoohey.artist a ON a.artistid = w.artistid
第二点是你在聚合行。 GROUP BY W.artistid, A.FirstName, A.LastName
告诉DBMS聚合行,以便每个艺术家获得一个结果行。使用having count(*) > 1
,您说您只希望艺术家拥有多项作品。但是在您的select子句中,您正在展示作品(W.workid, W.title, W.medium, W.description
)。哪一个?如果每位艺术家只展示一行,每位艺术家都有不止一件作品,那么你会展示一位艺术家的作品吗? DBMS注意到您忘记告诉它选择什么并引发错误。现在你可能会同意使用给定的GROUP BY和HAVING子句的查询没有任何意义。