2017-08-01 75 views
0

我有2個表:MySQL的:選擇相對於第二表

實體:

id 

狀態:

id 
entity_id 
status 

每個實體可以有多個狀態,我需要僅選擇具有「已付款」狀態並且沒有「已取消」狀態的實體。我如何做一個適當的加入呢?

實施例:

entities: id 7 
entities: id 8 
entities: id 9 
entities: id 10 
statuses: id 1, entity_id 7, status 'paid' 
statuses: id 2, entity_id 7, status 'canceled' 
statuses: id 3, entity_id 8, status 'paid' 
statuses: id 4, entity_id 10, status 'onhold' 
statuses: id 5, entity_id 8, status 'whatever' 

只有具有的8的ID entiry將被選擇一次。

回答

1

也許像下面這樣:

 

SELECT e.* 
FROM 
entities as e INNER JOIN statuses as spaid 
      ON e.id = spaid.entity_id and spaid.status = 'paid' 
    LEFT JOIN statuses as scanceled 
      ON e.id = scanceled.entity_id and scanceled.status = 'canceled' 
WHERE scanceled.id IS NULL 
 

ŧ他首次加入需要具有「已付款」身份的實體。

第二加入將增加用於具有「取消」狀態,或者爲null,實體實體第二狀態沒有被取消的狀態

where子句然後過濾條目,只服用該行認爲作爲'取消'狀態具有NULL。

+0

它似乎這樣做。謝謝! –

1

就是這樣。我們按照實體ID對狀態進行分組,並在分組後將其過濾爲只有那些具有MIN和MAX付費的狀態。實體7將具有「取消」的最小值和「已付」的最大值,因此被排除。

SELECT e.* 
FROM 
entities e 
INNER JOIN 
(
    SELECT entity_id FROM statuses s 
    GROUP BY entity_id 
    HAVING 
    MIN(CASE WHEN status = 'canceled' THEN status ELSE 'not canceled' END) = 'not canceled' AND 
    MAX(CASE WHEN status = 'paid' then 'paid' ELSE 'not paid' END) = 'paid' 
) a 
ON 
    a.entity_id = e.id 

多一點的MIN和MAX,按您的評論:

你說的事情可以有很多的狀態,但我們真的只在付費的東西感興趣,那麼我們只有在那些支付感興趣事情,如果他們從來沒有取消。我們做什麼,然後與狀態是:

  • 又比「取消」其他一切都變成「不取消」
  • 又比其他一切「有償」轉變爲「未支付」
  • 鏈接行條目起來和尋找的「有償」配對/「不取消」

要明白我的意思是,看看:

SELECT 
    entity_id, 
    CASE WHEN status = 'paid' then 'paid' ELSE 'not paid' END as is_paid, 
    CASE WHEN status = 'canceled' THEN status ELSE 'not canceled' END as is_cancelled 
FROM 
    status 

現在採取LO確定在:

SELECT 
    entity_id, 
    MAX(CASE WHEN status = 'paid' then 'paid' ELSE 'other' END) as is_paid, 
    MIN(CASE WHEN status = 'canceled' THEN status ELSE 'not canceled' END) as is_cancelled 
FROM 
    status 
GROUP BY 
    entity_id 

這是一個「透視」操作;它在概念上將行變成列。項目7的多行成爲具有多列的單行。因爲按字母順序,「付費」是在「未付款」之後,「取消」在「

之前」,因此這是我們尋找「已付款」/「未取消」配對的方式。點,我們可以這樣說:

SELECT * FROM entities INNER JOIN 
(
    SELECT 
    entity_id, 
    MAX(CASE WHEN status = 'paid' then 'paid' ELSE 'other' END) as is_paid, 
    MIN(CASE WHEN status = 'canceled' THEN status ELSE 'not canceled' END) as is_cancelled 
    FROM 
    status 
    GROUP BY 
    entity_id 
) finder 
ON 
    entities.id = finder.entity_ID 
WHERE 
    finder.is_paid = 'paid' and finder.is_canceled = 'not canceled' 

這只是一個有點短做這個過濾較早使用具有而不是以後使用WHERE

+0

謝謝。你能解釋一下這個有最小和最大值嗎? –

+0

對不起。這將只選擇已經支付狀態而沒有其他狀態的實體。但實體可以有多個狀態。我所關心的所有付款都存在並取消不存在。我通過添加另一個示例行更新了我的最初問題。 –

+0

修正答案 –

相關問題