MySQL SELECT WHERE OR - 仅当second为空时才选择一行

时间:2016-01-20 17:50:18

标签: mysql sql mariadb

我正在加入2个表,例如

PRODUCTS (PRODUCT_ID, NAME)

PRICE_LEVELS (PRODUCT_ID, PRICE, PRICE_LVL_NAME )

(ofc。它简化了,有几个连接)。

PRICE_LEVELS表中,我有一些价格级别名称的可能性,让我们说" DEFAULT "和LEVEL1,所以我们得到了类似的东西:

PRODUCT_ID | PRICE | PRICE_LVL_NAME
1          | 100   | _DEFAULT_
1          | 50    | LEVEL1
2          | 130   | _DEFAULT_

两个表都在视图中连接。

我需要的是获得价格,但只需要一次 - 我的意思是如果定义了LEVEL1,选择那个,否则选择DEFAULT。

与此同时,我使用了GROUP BY,似乎工作正常,但我不知道为什么(ofc。我已经使用了大量的测试数据而且它总是有效,但不确定,它是如何可靠的。)

让我们说我们的观点(合并两个表格)的名称为V_PRODUCTS,因此我正在运行查询:

SELECT * 
FROM `V_PRODUCTS` 
WHERE (PRICE_LVL_NAME = '_DEFAULT_' OR PRICE_LVL_NAME = 'LEVEL1') 
GROUP BY `PRODUCT_ID `;

所以问题是:

  1. 为什么上面的查询有效? GROUP BY总是选择LEVEL1,如果可用,则选择DEFAULT。这正是我的需要,但需要理解为什么它会以这种方式工作。

  2. 有没有办法在SQL中更明确地做到这一点?

  3. 更新:可以有无限数量的可能级别

4 个答案:

答案 0 :(得分:0)

Q1:它不可靠,它可能基于内部存储,可能随时发生变化。

Q2:使用外部联接加入表格两次并使用COALESCE返回最佳匹配:

SELECT ..., COALESCE(pl1.PRICE, pl2.PRICE)
FROM `V_PRODUCTS` as p 
LEFT JOIN PRICE_LEVELS as pl1
  ON p.PRODUCT_ID = pl1.PRODUCT_ID
 and PRICE_LVL_NAME = 'LEVEL1') 
LEFT JOIN PRICE_LEVELS as ply
  ON p.PRODUCT_ID = pl2.PRODUCT_ID
 and PRICE_LVL_NAME = '_DEFAULT_'

答案 1 :(得分:0)

我现在没有MySQL可以玩,但是你应该只需要替换这个MSSQL的IS NULL部分,以使它能够工作。

如果您在级别中不需要AlphaNum,或者可以添加一个INT字段,其中0是默认值,然后是1,依此类推,您可以将级别连接到自身以获得最大可用级别以加入到产品表。

    SELECT PRODUCTS.*, PriceLvl.*
    FROM [PRODUCTS] LEFT JOIN 
      (SELECT p1.*
       FROM PRICE_LEVELS p1 
            LEFT JOIN PRICE_LEVELS p2 ON 
            (p1.PRODUCT_ID = p2.PRODUCT_ID 
             AND p2.PRICE_LVL > p1.PRICE_LVL)
       WHERE p2.PRICE_LVL IS NULL) PriceLvl 
    ON PRODUCTS.PRODUCT_ID = PriceLvl.PRODUCT_ID

这需要

    PRODUCT_ID  NAME
             1  Tshirts
             2  Pants

    PRODUCT_ID  PRICE   PRICE_LVL
             1  10.00   0
             1  15.00   1
             2  40.00   0
             1  20.00   2

并给出

    PRODUCT_ID  NAME    PRODUCT_ID  PRICE   PRICE_LVL
             1  Tshirts          1  20.00   2
             2  Pants            2  40.00   0

答案 2 :(得分:0)

我为每个级别分配一个数值,默认为零,并将其存储在同一个表中。

Job.JobLocations

答案 3 :(得分:0)

WHERE price_level IN ('_DEFAULT_', 'mylevel')
ORDER BY
    price_level = '_DEFAULT_'
LIMIT 1

WHERE将获取1或2行。

price_level = '_DEFAULT_'默认为1,否则在0之前排序为0. 0,因此,如果存在'mylevel',它将首先出现。

LIMIT 1表示选择第一行(或唯一一行)。