如何从两个不同的表中选择count和另一个值?

时间:2017-03-14 03:37:15

标签: sql oracle

在oracle中,我有一个名为classes的表,它列出了船的类和另一个名为ships的表,列出了这些类的船的名称。现在我需要找出每个至少有3艘船只的船只,这些船只的船只沉没了多少次。为此,我有一个结果表,告诉我船名和结果。为此,我首先创建了一个视图:

CREATE VIEW classes_with_3_ships AS
    SELECT c.class
    FROM Classes c FULL OUTER JOIN Ships s ON s.class = c.class
    GROUP BY c.class
    Having COUNT(s.class) >= 3;

这列出了至少有3艘船只的所有类别。现在,我正在尝试使用此视图来计算结果“沉没”的结果。

SELECT c.class, Count(result)
FROM Outcomes o, classes_with_3_ships c
WHERE o.RESULT = 'sunk';

这不起作用,因为显然你不能同时选择c.class和count。那我怎么能做这个呢?

一些示例数据 对于课程

Insert Into Classes Values ('Renown','bc','Gt. Britain',6,15,32000);

Insert Into Classes Values ('Kongo','bc','Japan',8,14,32000);

Insert Into Classes Values ('Revenge','bb','Gt. Britain',8,15,29000);

对于船舶:

Insert Into Ships Values ('Haruna','Kongo',1915);

Insert Into Ships Values ('Hiei','Kongo',1914);

Insert Into Ships Values ('Kongo','Kongo',1913);

Insert Into Ships Values ('Ramilles','Revenge',1917);

Insert Into Ships Values ('Resolution','Revenge',1916);

Insert Into Ships Values ('Revenge','Revenge',1916);

Insert Into Ships Values ('Royal Oak','Revenge',1916);

所以视图的结果应该是

Revenge
Kongo

查询结果应为

Class        sunk_ships
Revenge          0
Kongo            1

以下是表格

Create Table Classes (
    class Varchar(40),
    type Char (2),
    country Varchar(15),
    numGuns Int,
    bore Int,
    displacement Int
);
Create Table Ships (
    name Varchar(40),
    class Varchar(40),
    launched Int
);
Create Table Outcomes(
    ship Varchar(40),
    battle Varchar(40),
    result Char(7)
);

3 个答案:

答案 0 :(得分:0)

您可以在没有视图的情况下尝试它,而是使用子查询。

尝试此查询:

from elasticsearch import Elasticsearch, RequestsHttpConnection
import datetime
import socket
from requests_aws4auth import AWS4Auth


class EsHelper():
    conn = ""
    index = "index"
    HOSTNAME = socket.gethostname()

def __init__(self):
    self.conn = Elasticsearch(['localhost:9200'])



    exist = self.conn.indices.exists(self.index)
    if not(exist):
        self.conn.indices.create('index', body={
            'settings': {
                'analysis': {
                    'filter': {
                        'autocomplete_filter': {
                            'type': 'edge_ngram',
                            'min_gram': 1,
                            'max_gram': 20
                        }
                    },
                    'analyzer': {
                        'autocomplete': {
                            'type': 'custom',
                            'tokenizer': 'standard',
                            'filter': [
                                'lowercase',
                                'autocomplete_filter'
                            ]
                        }
                    }
                },
                'index': {
                    'number_of_shards': '5',
                    'number_of_replicas': '1'
                }
            }, 
        })

def EsAddIndex(self, index, type, id, body):
    self.conn.index(index=index, doc_type=type, id=id, body=body)

def EsUpdateIndex(self, index, type, id, body):
    self.conn.update(index=index, doc_type=type, id=id, body=body)

def EsSearch(self, index, page, size, searchTerm):
    body = {
        'query': {
            'match': searchTerm
        },
        'sort': {
                'created': {
                    'order': 'desc'
                }
        },
        'filter': {
                'term': {
                    'super_verification': 'verified'
                }
        }
    }
    res = self.conn.search(index=index, body=body)
    output = []
    for doc in res['hits']['hits']:
        output.append(doc['_source'])
    return output

内部查询查找至少有3艘船的类。这用于过滤外部查询,它将三个表连接在一起。

不需要视图。

要注意的一件事是" sunk"这个词。如果它总是小写的,那很好。否则,您可能希望将o.result包含在LOWER函数中。

这能为您提供所需的结果吗?

答案 1 :(得分:0)

假设结果表具有发货名称列,并且结果可以使用

select c.class, count(*)
from   classes c,
    ships   s,
    outcomes o
where c.class = s.class
      and s.name = o.ship(+)
      and c.class in (select class from classes_with_3_ships)
      and o.result ='sunk'
group by c.class

答案 2 :(得分:0)

如果您想创建一个包含船名的视图,可以使用下面的内容。但是在这个视图中包含船名并不是必需的。我将在下面详细说明。

CREATE OR REPLACE VIEW CLASSES_WITH_3_SHIPS AS
SELECT CLASS_NAME, SHIP_NAME
FROM(
SELECT CLASSES.CLASS AS CLASS_NAME, 
COUNT(*) OVER (PARTITION BY CLASSES.CLASS) AS COUNT_SHIPS,
SHIPS.NAME AS SHIP_NAME
FROM CLASSES
INNER JOIN SHIPS
ON CLASSES.CLASS = SHIPS.CLASS)
WHERE COUNT_SHIPS > 2;

SELECT * FROM CLASSES_WITH_3_SHIPS;
CLASS_NAME  SHIP_NAME
Kongo       Kongo
Kongo       Hiei
Kongo       Haruna
Revenge     Revenge
Revenge     Resolution
Revenge     Royal Oak
Revenge     Ramilles

但是,实际上并不需要计算每个级别的沉没船只。 通过以下视图,人们仍然可以找到计数。

CREATE OR REPLACE VIEW CLASSES_WITH_3_SHIPS AS
SELECT CLASS_NAME FROM (SELECT SHIPS.CLASS AS CLASS_NAME, 
COUNT(*) COUNT_SHIPS 
FROM SHIPS
GROUP BY SHIPS.CLASS) 
WHERE COUNT_SHIPS > 2;

SELECT * FROM CLASSES_WITH_3_SHIPS;
CLASS_NAME
Revenge
Kongo

然后,您可以执行如下所示的查询来获取每个类别的沉没船只的数量。

向OUTCOMES添加一些测试数据:

INSERT INTO OUTCOMES VALUES('Haruna', NULL, 'scrap');
INSERT INTO OUTCOMES VALUES('Kongo', NULL,'active');
INSERT INTO OUTCOMES VALUES('Heiei', NULL, 'scrap');
INSERT INTO OUTCOMES VALUES('Ramilles', NULL, 'scrap');
INSERT INTO OUTCOMES VALUES('Resolution', NULL,'active');
INSERT INTO OUTCOMES VALUES('Revenge', NULL,'sunk');
INSERT INTO OUTCOMES VALUES('Royal Oak', NULL,'sunk');

然后按班级取出沉没船只的数量。如果一个类没有沉没船只,则返回零:

SELECT CLASSES_WITH_3_SHIPS.CLASS_NAME, 
COALESCE(SUNK_SHIP.SUNK_COUNT,0) AS SUNK_COUNT
FROM CLASSES_WITH_3_SHIPS
LEFT OUTER JOIN (
SELECT SHIPS.CLASS CLASS_NAME, COUNT(*) SUNK_COUNT
FROM SHIPS INNER JOIN OUTCOMES
ON SHIPS.NAME = OUTCOMES.SHIP
WHERE OUTCOMES.RESULT = 'sunk'
GROUP BY SHIPS.CLASS) SUNK_SHIP
ON CLASSES_WITH_3_SHIPS.CLASS_NAME = SUNK_SHIP.CLASS_NAME;

结果:

CLASS_NAME  SUNK_COUNT
Revenge     2
Kongo       0

希望这能满足您的需求。