加入并过滤一对多关系

时间:2015-10-02 18:43:51

标签: mysql sql database h2

我需要一些关于SQL查询的最佳结构的帮助。我有这样的模特:
segment of database model

我正在尝试表格NON_NATURAL_PERSONNNP_NAME之间的某种联接。因为我在表NNP_NAME中为一个人提供了很多名字,所以我不能一对一SELECT * from NON_NATURAL_PERSON inner join NNP_NAME等。这样我就会为每个人的名字获得额外的行。

表格中的数据:
PERSON data NON_NATURAL_PERSON data NNP_NAME data
如何扩展此查询以在下面显示的图片上获得标记为红色的行?我想要的查询标准是:只有存在才能加入typeA的名称。如果没有,请加入typeB的名称。如果两者都不存在typeC的连接名。

SELECT nnp.ID, name.NAME, name.TYPE 
FROM NON_NATURAL_PERSON nnp
INNER JOIN NNP_NAME name ON (name.NON_NATURAL_PERSON = nnp.ID)

query result

2 个答案:

答案 0 :(得分:1)

如果类型拼写完全符合它(typeA,typeB,typeC),那么你可以使用MIN()函数:

SELECT NON_NATURAL_PERSON, MIN(type) AS min_type
FROM NNP_NAME
GROUP BY NON_NATURAL_PERSON

如果您还想要用户名,可以使用此查询:

SELECT
  n1.NON_NATURAL_PERSON AS ID,
  n1.Name,
  n1.Type
FROM
  NNP_NAME n1 LEFT JOIN NNP_NAME n2
  ON n1.NON_NATURAL_PERSON = n2.NON_NATURAL_PERSON
     AND n1.Type > n2.type
WHERE
  n2.type IS NULL

请参阅此fiddle。如果类型未按字面顺序排序,请更改此行:

     AND n1.Type > n2.type

用这个:

     AND FIELD(n1.Type, 'TypeA', 'TypeB', 'TypeC') >
         FIELD(n2.type, 'TypeA', 'TypeB', 'TypeC')

MySQL FIELD(str,str1,str2,...)函数返回str1,str2,...列表中str的索引(位置),如果未找到str,则返回0。你想得到第一个"按类型排序的记录,用于每个NON_NATURAL_PERSON。有多种方法可以获得此信息,我选择了自我加入:

ON n1.NON_NATURAL_PERSON = n2.NON_NATURAL_PERSON
   AND n1.Type > n2.type -- or filed function

WHERE条件:

WHERE n2.type IS NULL

这将返回连接未成功的所有行 - 当n2.type小于n1.type时,连接不会成功 - 它将返回第一个记录。

修改

如果您想要一个独立于平台的解决方案,避免创建新表,您可以使用CASE WHEN,只需更改

AND n1.Type > n2.Type

AND
  CASE
    WHEN n1.Type='TypeA' THEN 1
    WHEN n1.Type='TypeB' THEN 2
    WHEN n1.Type='TypeC' THEN 3
  END
  >
  CASE
    WHEN n2.Type='TypeA' THEN 1
    WHEN n2.Type='TypeB' THEN 2
    WHEN n2.Type='TypeC' THEN 3
  END

答案 1 :(得分:1)

缺少一条信息。你说:

Always join name of typeA only if exists. If not, join name of typeB. If neither exists join name of typeC.

但是你没有指明为什么你喜欢typeA而不是typeB。此信息不包含在您的数据中。 在@fthiella的答案中,假定是词典编纂,或者使用FIELD给出任意顺序。这也是为什么需要两个与表nnp_name连接的原因。

您可以通过添加表name_type (id, name, order)并更改类型列以包含ID来解决此问题。这将允许您以干净的方式添加缺少的信息。

通过与此新表的附加连接,您将能够获得每行的首选nnp_name。