将INNER JOIN和LEFT JOIN与日期选择相结合

时间:2014-07-18 14:17:53

标签: mysql join

我的数据库有一个复杂的查询,我想加入几个表 像这样:

SELECT cad.artc, prod.sku, prod.product_id, prodclass.entity_id, prodclass.field_product_class_tid, tax.tid, substring(tax.name, 3), block1.field_product_blocktime_1_value, block1.field_product_blocktime_1_value2
FROM _cadencier as cad
INNER JOIN commerce_product as prod
on prod.sku = cad.artc
AND cad.adrc = '000'
AND cad.relc = '000028'
INNER JOIN field_data_field_product_class as prodclass
on prodclass.entity_id = prod.product_id
INNER JOIN field_data_field_product_limited as limited
on limited.entity_id = prod.product_id
AND limited.field_product_limited_value = '0'
INNER JOIN taxonomy_term_data as tax
ON prodclass.field_product_class_tid = tax.tid
AND tax.language = 'nl'
LEFT JOIN field_data_field_product_blocktime_1 as block1
ON block1.entity_id = prod.product_id
GROUP BY tax.name, prod.title;

给我以下结果:

enter image description here

我想在块时间值之间排除今天的日期为NULL的所有产品。但为了做到这一点,我不得不使用LEFT JOIN而不是INNER JOIN。但是当我尝试像

这样的东西时
WHERE block1.field_product_blocktime_1_value >= DATE(NOW())
AND block1.field_product_blocktime_1_value2 <= DATE(NOW()) 

我最终没有结果......
我加入了错误的方式吗?

3 个答案:

答案 0 :(得分:0)

好的...对不起误读了这个问题......

感谢你指出@michiel。

您可以查看:

WHERE (DATE(NOW()) NOT BETWEEN block1.field_product_blocktime_1_value AND block1.field_product_blocktime_1_value2) OR block1.field_product_blocktime_1_value IS NULL

答案 1 :(得分:0)

老答案:对问题的误解

要获取左连接表的NULL值,您必须在连接的ON子句中包含条件。使用WHERE子句中的条件将OUTER JOIN隐式更改为INNER:

...
LEFT JOIN field_data_field_product_blocktime_1 as block1
ON block1.entity_id = prod.product_id
AND block1.field_product_blocktime_1_value >= DATE(NOW())
AND block1.field_product_blocktime_1_value2 <= DATE(NOW())
GROUP BY tax.name, prod.title;

编辑回答

如果您只想要那些带有封锁的行,那么您必须使用INNER JOIN。 您的field_product_blocktime_1_value似乎是阻止时间的开始和block1.field_product_blocktime_1_value2

因为你需要行,当前日期在

之间
`field_product_blocktime_1_value`

block1.field_product_blocktime_1_value2

您应该交换运算符以获得所需的结果:

...
INNER JOIN field_data_field_product_blocktime_1 as block1
ON block1.entity_id = prod.product_id
WHERE 
    block1.field_product_blocktime_1_value <= DATE(NOW())
AND 
    block1.field_product_blocktime_1_value2 >= DATE(NOW())
GROUP BY tax.name, prod.title;

答案 2 :(得分:0)

这是获得指定结果的一种方法(因为我没有看到它)

修改您的查询以删除此内容:

LEFT JOIN field_data_field_product_blocktime_1 as block1
ON block1.entity_id = prod.product_id
WHERE block1.field_product_blocktime_1_value >= DATE(NOW())
AND block1.field_product_blocktime_1_value2 <= DATE(NOW()) 

并将其替换为:

 WHERE NOT EXISTS 
       ( SELECT 1
           FROM field_data_field_product_blocktime_1 block1
           WHERE block1.field_product_blocktime_1_value   <= DATE(NOW())
             AND block1.field_product_blocktime_1_value2  >= DATE(NOW()) 
             AND block1.entity_id = prod.product_id
       )

请注意,我们想要找到的是block1表中的行,其中当前日期在两个列值之间,对于给定的product_id。如果我们找到一个“匹配”行,那么我们想要排除返回的行。

要使用反连接模式执行等效操作,我们可以用以下内容替换它:

  LEFT
  JOIN field_data_field_product_blocktime_1 block1
    ON block1.entity_id = prod.product_id
   AND block1.field_product_blocktime_1_value  <= DATE(NOW())
   AND block1.field_product_blocktime_1_value2 >= DATE(NOW()) 
 WHERE block1.entity_id IS NULL

同样,我们在block1中寻找匹配的行(就像我们对NOT EXISTS谓词所做的那样。“技巧”在WHERE子句中,我们使用了谓词,排除所有匹配的行,通过测试我们知道如果找到匹配项将为非NULL的列。

此外,至少在调试时,请删除GROUP BY子句,并添加ORDER BY子句。

GROUP BY子句要么折叠行,要么隐藏值,要么不折叠任何行,在这种情况下可能没有必要。

我怀疑你的意思是使用ORDER BY子句而不是GROUP BY子句,这两个相当不同。 (GROUP BY的ANSI标准的MySQL扩展过于宽松;带有GROUP BY的查询会在其他RDBMS中引发错误。)这只是一种怀疑;值得一提的是,万一你还没考虑过。