SQL检索具有多条记录

时间:2016-06-04 16:54:02

标签: sql database

我遇到了“不是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;

4 个答案:

答案 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子句的查询没有任何意义。