MySQL左连接 - 非空或第一行

时间:2016-10-25 15:43:06

标签: mysql left-join

我们有两张桌子,

PRODUCT_INDEX:

+----------------+---------------+------+-----+---------+-------+
| Field          | Type          | Null | Key | Default | Extra |
+----------------+---------------+------+-----+---------+-------+
| PRODUCT_NUMBER | varchar(25)   | NO   | PRI |         |       |
| VENDOR_NUMBER  | varchar(10)   | NO   | PRI |         |       |
| VENDOR_PRODUCT | varchar(25)   | YES  | MUL |         |       |
+----------------+---------------+------+-----+---------+-------+

产品:

+------------------+---------------+------+-----+---------+-------+
| Field            | Type          | Null | Key | Default | Extra |
+------------------+---------------+------+-----+---------+-------+
| PRODUCT_NUMBER   | varchar(25)   | NO   | PRI |         |       |
| DESCRIPTION_ENG  | varchar(500)  | YES  | MUL |         |       |
| STATUS           | varchar(1)    | YES  |     |         |       |
+------------------+---------------+------+-----+---------+-------+

如果我们运行此查询一个PRODUCT_INDEX:

SELECT * FROM PRODUCT_INDEX WHERE PRODUCT_NUMBER = '900338'

我们按此顺序获得3个结果。

+----------------+---------------+----------------+
| PRODUCT_NUMBER | VENDOR_NUMBER | VENDOR_PRODUCT |
+----------------+---------------+----------------+
| 900338         | F00045        |                |
| 900338         | F00509        |                |
| 900338         | F01041        | CSR6719-2      |
+----------------+---------------+----------------+

现在我需要进行查询,从表 PRODUCT 加入 只有一行 中选择所有产品表 PRODUCT_INDEX 。如果某一行的字段VENDOR_PRODUCT不为空,我们首先要使用此行。如果所有行都包含字段VENDOR_PRODUCT,我们想要获取第一行,如果所有行都不包含字段VENDOR_PRODUCT,我们希望将第一行包含在内。

现在我有传统的左连接查询(对于这个例子,我只选择一个产品,但我的查询是针对PRODUCT表中的所有产品):

SELECT
  P.PRODUCT_NUMBER,
  P.DESCRIPTION_ENG,
  P.STATUS,
  PCI.VENDOR_NUMBER,
  PCI.VENDOR_PRODUCT
FROM
  PRODUCT P
LEFT JOIN
  PROD_CROSS_INDEX PCI
ON
  PCI.PRODUCT_NUMBER = P.PRODUCT_NUMBER
WHERE
  P.PRODUCT_NUMBER = '900338';

此查询返回3行,因为它们在PRODUCT_INDEX中有3行匹配。

我如何查询?

编辑2:

这是我现在的完整查询:

SELECT
  P.*,
  IP.master AS MASTER_PACK,
  IP.inner AS INNER_PACK,
  PO.INFO1,
  PO.INFO2,
  PO.INFO3,
  PO.INFO4,
  PO.INFO5,
  PO.INFO6,
  PO.INFO7,
  PO.INFO8,
  PO.INFO9,
  PO.INFO10,
  PO.INFO11,
  PO.INFO12,
  PO.MEMO_ENG1,
  PO.MEMO_FR1,
  PO.FLAGS1,
  PO.MEMO_ENG2,
  PO.MEMO_FR2,
  PO.FLAGS2,
  PO.MEMO_ENG3,
  PO.MEMO_FR3,
  PO.FLAGS3,
  PO.PICTURE,
  PP.PRICE_1,
  PP.PRICE_2,
  PP.PRICE_3,
  PP.PRICE_4,
  PP.PRICE_5,
  PP.PRICE_6,
  MAX(IFNULL(PCI.VENDOR_PRODUCT, 0)) AS VENDOR_PRODUCT
FROM
  PRODUCT P
LEFT JOIN
  PRODUCT_OTHER PO
ON
  PO.PRODUCT_NUMBER = P.PRODUCT_NUMBER
LEFT JOIN
  PRODUCT_PRICES PP
ON
  PP.PRODUCT_NUMBER = P.PRODUCT_NUMBER
LEFT JOIN
  addison_intranet.ae_produit IP
ON
  IP.sku = P.PRODUCT_NUMBER
LEFT JOIN
  PROD_CROSS_INDEX PCI
ON
  PCI.PRODUCT_NUMBER = P.PRODUCT_NUMBER
WHERE
  P.STATUS != 'D' AND P.MASTER = '' AND P.PRODUCT_NUMBER NOT LIKE '%ECH%' AND P.PRODUCT_NUMBER NOT LIKE '%CARTE%' AND P.PRODUCT_NUMBER NOT LIKE '%ZZZ%' AND P.UNIT != 'KIT'
GROUP BY
  P.PRODUCT_NUMBER
ORDER BY
  P.PRODUCT_NUMBER

1 个答案:

答案 0 :(得分:1)

您可以使用聚合功能

  SELECT
    P.PRODUCT_NUMBER,
    P.DESCRIPTION_ENG,
    P.STATUS,
    max(ifnull(PCI.VENDOR_NUMBER, 0)),
    max(ifnull(PCI.VENDOR_PRODUCT, 0)
  FROM
    PRODUCT P
  LEFT JOIN
    PROD_CROSS_INDEX PCI
  ON
    PCI.PRODUCT_NUMBER = P.PRODUCT_NUMBER
  GROUP BY   P.PRODUCT_NUMBER,    P.DESCRIPTION_ENG, P.STATUS
  ORDER BY PCI.VENDOR_PRODUCT desc limit 1;