SQL - 用于排除行的内部联接

时间:2017-01-25 13:24:56

标签: mysql sql laravel-5 eloquent

我在laravel应用程序中有以下表格:

basket
------
id  PK
user_id FK
coupon_id FK

basket_items
------------
id PK
basket_id FK
product_id FK
quantity 
purchaseable_id   
purchaseable_type -- e.g. App\Job, App\CV

products
--------
id PK
name  -- e.g. standard job listing, premium job listing, cv download
price

jobs
----
id PK
product_id FK
title
start_dt
expiry_dt
description

cvs
------
id PK
name

purchaseable_id表中的purchaseable_typebasket_items是多态关系。例如。用户可以将作业添加到他们的购物篮中,这是一个高级产品列表 - 在这种情况下,purchaseable_id将是作业表中作业的id,而purchaseable_type将是App\Job。 basket_items表中的示例行可能如下所示:

id | basket_id | product_id | quantity | purchaseable_id | purchaseable_type
----------------------------------------------------------------------------
1  | 1         |  1         |   1      |     1           | App\Job   
2  | 1         |  3         |   1      |     1           | App\CV

我想要列出用户的所有basket_items,但如果purchaseable_type为App\Job且作业已过期,则排除项目。

我尝试过以下操作但如果作业已过期则排除所有行,即它排除每个purchaseable_type的项目

select t1.*, t2.* 
from baskets t1
inner join basket_items t2 on t2.basket_id = t1.id
left join jobs t3 on t3.id = t2.purchaseable_id and t2.purchaseable_type = 'App\\Job' 
where t1.user_id = 1 and t3.expiry_dt > now()  

2 个答案:

答案 0 :(得分:0)

使用左连接时,表中与连接条件不匹配的所有字段均为NULL。因此,在这种情况下,当您从basket_itemsjobs的加入与加入条件不匹配时,从jobs提取的字段都是NULL。由于如果t3.expiry_dt > now()false,表达式t3.expiry_dt将始终返回NULL,您将无法获得这些记录。

解决这个问题的方法是更改​​WHERE子句以允许NULL:

where t1.user_id = 1 and ( t3.expiry_dt > now() OR t3.expiry_dt IS NULL)

答案 1 :(得分:0)

不要加入职位表。您只想将其用作条件,因此它属于SELECT * FROM `departament` INNER JOIN `fakultet` ON "departament.#ID_Fakultet"="fakultet.ID_Fakultet" WHERE

ON

这使您的查询更具可读性,因此不易出现(未来)错误,即提供更好的可维护性。