2016-04-14 147 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)