2016-04-14 108 views
0

我在使用PostgreSQL试图找出如何找到符合特定条件的最常见值时遇到了很多麻烦。 ID是本书的ID号码,这意味着重复的数字意味着该书有多个副本。寻找最常见的值

我有2代表的位置:

Table A: 
=====+=================== 
ID | Condition 
------------------------- 
1 | Taken 
1 | 
1 | Taken 
1 | 
2 | Taken 
3 | Taken 
3 | 
3 | Taken 
3 | Taken 
4 | 
4 | Taken 
etc. 

Table B: 
=====+=================== 
ID | Name 
------------------------- 
1 | BookA 
2 | BookB 
3 | BookC 
4 | BookD 
etc. 

我需要的是简单地找到这本书采取了最副本,简单地把书印出来的名字。在这种情况下,我需要的是:

BookC 

问题是,我无法弄清楚如何找到每个个人ID有多少书籍。我尝试使用临时表,像这样:

CREATE TEMP TABLE MostCommon AS 
    (SELECT ID 
    FROM TableA 
    WHERE SUM(CASE WHEN Condition>0 then 1 else 0 END) 
    ) 
    SELECT NAME FROM TableB, MostCommon WHERE 
    MostCommon.ID = TableB.ID; 

但它要么抛出一个错误,或根本不给我我需要什么。任何帮助将不胜感激。

+0

数据使没有道理;这意味着有多个记录完全相同?请发布一个[最小,完整,可验证的示例](https://stackoverflow.com/help/mcve)我们可以运行的SQL代码,以获取与您相同的架构和数据。 – bignose

+0

@bignose“ID”号码是本书的ID。每个都有多个副本,这就是ID号在第一个表中重复多次的原因。 – Anstane

回答

1

好了,首先,我认为你的列和表名是区分大小写的,这意味着你必须用双排引号。要以“采取的”副本数量打印大多数“采取”一书的名字,你可以使用简单的aggragete count(),然后命令输出下降,并在年底将输出限制为1列,如:

SELECT 
    b."ID", 
    b."Name", 
    count(*) as takenCount 
FROM "TableA" a 
    JOIN "TableB" b ON a."ID" = b."ID" 
WHERE a."Condition" = 'Taken' 
GROUP BY b."ID", b."Name" 
ORDER BY 3 DESC 
LIMIT 1; 
+1

谢谢。这是最清楚和最容易理解的答案。它确实有效。 – Anstane

0
CREATE TEMP TABLE MostCommon AS 
(SELECT id, (sum(ID)/id) book_taken FROM tableA where condition = 'Taken' group by id); 


select name from tableB t2 join MostCommon mc on mc.id = t2.id where mc.id in (select max(book_taken) from MostCommon) 
0

为了使数据合理(即没有重复记录),我必须稍微改变模式。

CREATE TABLE book_condition (
    created TIMESTAMP, 
    book_id INTEGER, 
    condition VARCHAR, 
    PRIMARY KEY (created, book_id)); 

INSERT INTO book_condition (created, book_id, condition) 
VALUES 
    ('2016-01-01 08:30', 1, 'Taken'), 
    ('2016-01-01 08:35', 1, ''), 
    ('2016-01-01 08:40', 1, 'Taken'), 
    ('2016-01-01 08:45', 1, ''), 
    ('2016-01-01 08:50', 2, 'Taken'), 
    ('2016-01-01 08:55', 3, 'Taken'), 
    ('2016-01-01 09:00', 3, ''), 
    ('2016-01-01 09:05', 3, 'Taken'), 
    ('2016-01-01 09:10', 3, 'Taken'), 
    ('2016-01-01 09:15', 4, ''), 
    ('2016-01-01 09:20', 4, 'Taken'); 

CREATE TABLE book (
    book_id INTEGER, 
    name VARCHAR, 
    PRIMARY KEY (book_id)); 

INSERT INTO book (book_id, name) 
VALUES 
    (1, 'BookA'), 
    (2, 'BookB'), 
    (3, 'BookC'), 
    (4, 'BookD'); 

然后,问题分解成:

  • 多少每本书的拷贝曾经采取?
SELECT 
    book_id, 
    COUNT(book_id) AS total_taken 
FROM book_condition 
WHERE 
    condition = 'Taken' 
GROUP BY book_id 
; 
book_id | total_taken 
---------+------------- 
     1 |   2 
     2 |   1 
     3 |   3 
     4 |   1 
(4 rows) 
  • 如何通过total_taken值排名记录?
SELECT 
    book_id, 
    total_taken, 
    RANK() OVER (
     ORDER BY total_taken DESC 
     ) AS total_taken_rank 
FROM (
    SELECT 
     book_id, 
     COUNT(book_id) AS total_taken 
    FROM book_condition 
    WHERE 
     condition = 'Taken' 
    GROUP BY book_id 
    ) AS bt 
ORDER BY total_taken_rank ASC 
; 
book_id | total_taken | total_taken_rank 
---------+-------------+------------------ 
     3 |   3 |    1 
     1 |   2 |    2 
     2 |   1 |    3 
     4 |   1 |    3 
(4 rows) 
  • 如何获得这本书的名字包含其键(id)值的查询结果呢?
SELECT 
    b.book_id, 
    b.name, 
    bt.total_taken, 
    RANK() OVER (
     ORDER BY bt.total_taken DESC 
     ) AS total_taken_rank 
FROM 
    book AS b 
    LEFT JOIN (
     SELECT 
      book_id, 
      COUNT(book_id) AS total_taken 
     FROM book_condition 
     WHERE 
      condition = 'Taken' 
     GROUP BY book_id 
     ) AS bt 
     USING (book_id) 
ORDER BY 
    total_taken_rank ASC, 
    book_id ASC 
; 
book_id | name | total_taken | total_taken_rank 
---------+-------+-------------+------------------ 
     3 | BookC |   3 |    1 
     1 | BookA |   2 |    2 
     2 | BookB |   1 |    3 
     4 | BookD |   1 |    3 
(4 rows) 
  • 如何只得到结果中的排名最高的记录?
SELECT 
    br.book_id, 
    br.name, 
    br.total_taken 
FROM (
    SELECT 
     b.book_id, 
     b.name, 
     bt.total_taken, 
     RANK() OVER (
      ORDER BY bt.total_taken DESC 
      ) AS total_taken_rank 
    FROM 
     book AS b 
     LEFT JOIN (
      SELECT 
       book_id, 
       COUNT(book_id) AS total_taken 
      FROM book_condition 
      WHERE 
       condition = 'Taken' 
      GROUP BY book_id 
      ) AS bt 
      USING (book_id) 
    ) AS br 
WHERE 
    total_taken_rank = 1 
; 
book_id | name | total_taken 
---------+-------+------------- 
     3 | BookC |   3 
(1 row)