在同一个字段和同一个表中查询2个不同的项目

我很新的SQL,我不知道如何查询同一领域和同一个表内的2个不同的项目。 我在Excel VBA中使用SQL通过oledb编写这个附加到PostGreSQL数据源

基本上我有2个查询,我需要结合成一个查询。 第一个查询是主要组。 我需要先find代码为C10%的所有人。 那些与C10谁也有代码R110%

代码在srch表中,人名在person表中,这些代码由master_id = p.entity_id

以下是我需要结合的两个查询:

Dim DIAG As String DIAG = "SELECT DISTINCT master_id, eventdate, code, term, surname, forename " _ & "FROM srch INNER JOIN person p ON master_id=p.entity_id " _ & "WHERE code LIKE 'C10..%' " _ & "ORDER BY master_id " Dim DIAG As String DIAG = "SELECT DISTINCT master_id, eventdate, code, term, surname, forename " _ & "FROM srch INNER JOIN person p ON master_id=p.entity_id " _ & "WHERE code LIKE 'R110%' " _ & "ORDER BY master_id " 

这些表有100行,每个都有一个标识该人的master_id。 因此,行将是master_id = 1和code = C10。 接下来可能是master_id = 1和代码R110。

你是正确的,不同的代码不能存在于同一行

这有帮助吗?

 person table entity_id | surname | forename 1 | Smith | John 2 | Mouse | Mickey 3 srch table master_id | code | term | eventdate 1 |C10 | DM | 01/01/2000 2 |R110 | AL | 01/01/2001 1 |R110 | AL | 01/01/2002 

我需要找人1

 Result master_id|code|term| eventdate |surname|forename 1 |R110| AL | 01/01/2002| Smith | John 

由于列引用不合格,我们无法确定每个列引用引用哪个表。


build议:为了帮助未来的SQL读者,请考虑使用表名称来限定所有列引用,或者更好的是使用短的(唯一的)表别名。 那么未来的读者将不会在淘汰表定义以找出哪个表包含哪个列。)还要考虑当同一个名称的列被添加到查询中使用的另一个表时,这个SQL语句将会发生什么。 )


我们只需要猜测哪个表包含哪些列。

我build议使用GROUP BY子句的模式,而不是DISTINCT。

我build议计算一个expression式的结果集合,testing一个包含的行是否满足特定的条件。

然后对聚合进行testing,看是否存在(在组内)条件评估为TRUE的行。

举个例子:(未经testing)

 SELECT s.master_id , s.eventdate , s.code , s.term , p.surname , p.forename FROM srch s INNER JOIN person p ON p.entity_id = s.master_id WHERE ( s.code LIKE 'C10..%' OR s.code LIKE 'R110%' ) GROUP BY s.master_id , s.eventdate , s.code , s.term , p.surname , p.forename HAVING SUM(CASE WHEN s.code LIKE 'C10..%' THEN 1 ELSE 0 END) > 0 AND SUM(CASE WHEN s.code LIKE 'R110%' THEN 1 ELSE 0 END) > 0 ORDER BY s.master_id 

CASEexpression式将评估为1或0,为每一行。 SUM()聚合将总共1s和0s。 如果有任何满足条件的行(在一个“组”内),总计的回报将大于零。

如果代码LIKE'R110%'中没有行(在组内),则SUM()将计算为0,并且比较将计算为FALSE,并且该行将不会返回。

注意:聚合的比较在HAVING子句中,因为当WHERE子句中的条件被计算时,访问行时,聚合的结果不可用。

跟进

卫生署! 上面的查询不会返回行。 这是我的不好。 我们testing一些testing用例是有原因的。 它可以帮助我们识别doofus问题,例如上面我提到的查询中的问题。

该查询不可能返回任何行。 代码列(我没有真正注意到)在GROUP BY子句中。 所以HAVING子句中至less有一个聚合函数保证计算为零。

(我的问题是我没有注意到代码是GROUP BY中的一个列,Doh!)


如果SELECT列表中的所有列都需要匹配, 除了 “代码”列…(我不喜欢使用昂贵的相关子查询时,我们不必…),我们可以添加“EXISTS(相关子查询)。

如果master_id是entity_id的外键引用,而entity_id是person的主键…我们可以推迟join操作,直到得到srch的结果。

术语和事件是否也需要匹配,或只是代码? 我们如何编写查询取决于…


根据评论中的回复,term和event_date不需要匹配。 我们正在寻找srch中的行,对于同一个人(master_id),至less有一行使用C10代码,至less有一行使用R110代码。

在上面的查询中,标识这些master_id的值遵循相同的模式,对HAVING子句中的聚合使用GROUP BY和条件testing。

这是一个查询,应该返回具有C10代码和R110代码的master_id值。 这是我们可以testing的东西…它不会返回整个结果集,只会得到我们想要返回的master_id值:

 SELECT r.master_id FROM srch r WHERE ( r.code LIKE 'C10..%' OR r.code LIKE 'R110%' ) GROUP BY r.master_id HAVING SUM(CASE WHEN r.code LIKE 'C10..%' THEN 1 ELSE 0 END) > 0 AND SUM(CASE WHEN r.code LIKE 'R110%' THEN 1 ELSE 0 END) > 0 

一旦我们得到这个,我们可以使用该查询作为内联视图…包装在parens中,分配一个别名并引用它,就像它是一个表。 例如:

 SELECT q.* FROM ( SELECT r.master_id FROM srch r WHERE ( r.code LIKE 'C10..%' OR r.code LIKE 'R110%' ) GROUP BY r.master_id HAVING SUM(CASE WHEN r.code LIKE 'C10..%' THEN 1 ELSE 0 END) > 0 AND SUM(CASE WHEN r.code LIKE 'R110%' THEN 1 ELSE 0 END) > 0 ) q 

我们应该testingPostgreSQL是否会运行。 如果我们不能做到这一点,那就没有意义了。 一旦我们确认了运行,我们可以将一个连接添加到srch表中,获取具有与C10或R110代码匹配的master_id的行。

 SELECT q.master_id , s.code , s.term , s.event_date FROM ( SELECT r.master_id FROM srch r WHERE ( r.code LIKE 'C10..%' OR r.code LIKE 'R110%' ) GROUP BY r.master_id HAVING SUM(CASE WHEN r.code LIKE 'C10..%' THEN 1 ELSE 0 END) > 0 AND SUM(CASE WHEN r.code LIKE 'R110%' THEN 1 ELSE 0 END) > 0 ) q JOIN srch s ON s.master_id = q.master_id AND s.code LIKE 'R110%' 

我们可以在人员表中添加一个连接,通过主键查找检索给定的名字和姓氏。

  JOIN person p ON p.entity_id = s.master_id 

将适当的列引用添加到SELECT列表。 原始查询具有DISTINCT关键字。 我们可以补充说,或者我们可以添加GROUP BY子句。 任何。

我们可以从内联视图或srch表引用master_id,甚至可以引用person表中的entity_id。 join条件保证我们他们将是非空的和相等的。

结束了这样的事情(桌子只检查,没有testing):

 SELECT s.master_id , s.code , s.term , s.event_date , p.surname , p.forename FROM ( SELECT r.master_id FROM srch r WHERE ( r.code LIKE 'C10..%' OR r.code LIKE 'R110%' ) GROUP BY r.master_id HAVING SUM(CASE WHEN r.code LIKE 'C10..%' THEN 1 ELSE 0 END) > 0 AND SUM(CASE WHEN r.code LIKE 'R110%' THEN 1 ELSE 0 END) > 0 ) q JOIN srch s ON s.master_id = q.master_id AND s.code LIKE 'R110%' JOIN person p ON p.entity_id = s.master_id GROUP BY s.master_id , s.code , s.term , s.event_date , p.surname , p.forename ORDER BY s.master_id , s.code 

而且,如果我还没有再做其他doofus错误,我期望这将返回OP指定的结果。 (我一直试图提供一些评论,关于我们如何构build查询。)

我有兴趣找出这个烟球有多大。

另一个后续

另外,由于我们不需要返回C10行,所以查询实际上可能会更简单一些。 内联视图可以返回给我们与C10代码相关的master_id值,我们可以放弃HAVING子句和对聚合的testing。 这应该返回一个相当于上面的结果,也许甚至更快一点:

 SELECT s.master_id , s.code , s.term , s.event_date , p.surname , p.forename FROM ( SELECT r.master_id FROM srch r WHERE r.code LIKE 'C10..%' GROUP BY r.master_id ) q JOIN srch s ON s.master_id = q.master_id AND s.code LIKE 'R110%' JOIN person p ON p.entity_id = s.master_id GROUP BY s.master_id , s.code , s.term , s.event_date , p.surname , p.forename ORDER BY s.master_id , s.code 

这是在黑暗中的一枪。 这可能会或可能不会工作,因为我们仍然不知道您正在使用哪个DBMS。 这应该适用于sql服务器,也许为postgresql。 您可能需要稍微调整语法,具体取决于您实际使用的DBMS。 无论您使用哪个系统,请不要害怕使用别名和格式。

 SELECT s.master_id , s.eventdate , count(distinct s.code) as CodeCount , s.term , p.surname , p.forename FROM srch s INNER JOIN person p ON s.master_id = p.entity_id WHERE s.code LIKE 'C10..%' OR s.code like 'R110%' group by s.master_id , s.eventdate , s.term , p.surname , p.forename having count(distinct s.code) = 2 ORDER BY s.master_id 

你可以试试这个通配符和AND的方法来返回两个:

我假设R110可能跟着C10..反之亦然。

 Dim DIAG As String DIAG = "SELECT DISTINCT master_id, eventdate, code, term, surname, forename " _ & "FROM srch INNER JOIN person p ON master_id=p.entity_id " _ & "WHERE code LIKE '*R110*' AND code LIKE '*C10..*' " _ & "ORDER BY master_id "