SQL检索包含多条记录的数据
我遇到了一个“not a GROUP BY expression”错误 我需要搜索类似的标题,媒体和描述。 艺人表由艺人ID、艺人姓氏和艺人名组成。 工作表由工作ID、标题、媒介、描述、artistid组成 artistid是唯一的钥匙 列出数据库中记录有多个副本的任何艺术作品的详细信息SQL检索包含多条记录的数据,sql,database,Sql,Database,我遇到了一个“not a GROUP BY expression”错误 我需要搜索类似的标题,媒体和描述。 艺人表由艺人ID、艺人姓氏和艺人名组成。 工作表由工作ID、标题、媒介、描述、artistid组成 artistid是唯一的钥匙 列出数据库中记录有多个副本的任何艺术作品的详细信息 SELECT W.workid, W.title, W.medium, W.description, W.artistid, A.FirstName, A.LastName FROM dtoohey.work
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;
似乎表之间没有适当的连接(我建议有一个..你应该做正确的一个) 如果您希望按W.artistIid(别名每个艺术家的工作ID计数)分组,则不能在选择中包含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是否为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;
也许写一个答案(重点是@mathguy对缺少连接的特定性的观察,以及选择列与分组方式/拥有方式的组合不合适的观察)更好地找出问题所在,并给出如何增强问题的想法;-)。。。下一次我建议在这个问题上更加沉重,这样世界就不必在答案上如此沉重地工作
我不认为这是一个MySQL、Oracle或者什么数据库都不特定的问题,但更多的是一个SQL初学者的学习旅程。。。您可能还想在此处查找连接说明:
从问题中给出的最小信息子集开始:共享id(比如艺术家id)上的艺术家和作品相关的2个表
在PostgreSQL或ParStream这样的数据库中,直接引起麻烦的一件事是在既不按分组也不按聚合/过滤的group by查询中选择列。但我们要做的是:
创建表:
$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)
显示隐式内部联接:
$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)
使用伪条件显示显式内部联接,以让解析器通过我们的查询(Update:不要在家中使用它,只显示mish mash。):
现在,一个更有用的内部联接只匹配两个表中通过“创建者”关系关联的这些条目:
$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)
因此,在上面,我们盲目地相信数据管理部分能够神奇地输入艺术家id值,并且始终正确且符合我们的期望(在现实生活中,引用外键约束肯定会放置在工作表的列上(没有艺术家/创建者的作品不会将艺术家表指定为“第一个”)
在上面,您还可以看到,从表列表中进行选择与无任何约束的内部联接相同,即表工作中的所有条目与表艺术家中的所有条目的笛卡尔乘积
现在,您的查询(为最小表模型编辑了一点)除了我不清楚它的请求思想外,还出现了错误,如回答文本顶部所述:
$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列表中的不匹配:
$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...
您需要就您想要实现的目标提出建议,以获得一个单一答案(有效)。在此之前,以下是一些选项:
假设您仅在现有的艺术家和作品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;
删除任何组(直到问题提供了任务为什么需要该组的详细信息):
已格式化为不必水平滚动的查询:
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正确指出的那样,我编造了“完全内部连接”一词,我经常这样做,对不起。也许我的大脑需要笛卡尔填充来平衡左|右|完全外部连接-谁知道;-)我使用了scaisEdge答案并进行了编辑。我意识到如果我选择workid(唯一键),我将无法显示任何内容,但如果没有它,我的所有字段都将打开。如前所述,问题主要在于您尚未完全了解自己在做什么 第一点是您的联接。仅仅用逗号分隔表,您使用的语法在二十多年前就变得多余了。作为初学者,您似乎很少使用这种语法。您一定在一本非常古老的书或教程中找到过这种语法。简言之:不要这样联接表。使用显式联接。逗号意味着
交叉联接
。因此,您拥有的是:
FROM dtoohey.work W CROSS JOIN dtoohey.artist A
这意味着您将每一位艺术家与每一件作品相结合。这很可能不是您想要的。您希望加入相关的艺术家和作品。您的查询显示工作表中有一个artistid
,因此模型中的一位艺术家制作了一件作品。因此,合适的加入方式是:
FROM dtoohey.work w
INNER JOIN dtoohey.artist a ON a.artistid = w.artistid
第二点是,您正在聚合行。
groupby W.artistid,A.FirstName,A.LastName
告诉DBMS聚合行,这样每个艺术家都会得到一个结果行。having count(*)>1
表示您只希望艺术家有多个作品。但在select子句中,您显示的是一个作品(W.workid,W.title,W.medium,W.description
)。哪一个?如果每个艺术家只显示一行,并且每个艺术家有多个作品,那么您会显示艺术家的哪一个作品?DBMS会注意到您忘记告诉它要选择什么,并引发错误。现在您可能会同意,对给定GROUP BY和HAVING子句的查询没有意义。可能会显示准确的错误消息有用,否则,拥有count(*)>1对我来说似乎不合适,但这可能意味着我从来没有这样使用过。你是从工作和艺术家中选择的,两者之间没有任何关系?是吗
FROM dtoohey.work W CROSS JOIN dtoohey.artist A
FROM dtoohey.work w
INNER JOIN dtoohey.artist a ON a.artistid = w.artistid