2017-10-18 71 views
1

我試圖從同一個Group中提取所有行,直到我打斷點值B。下面的示例數據是有序的虛擬表格:如何從組中選擇所有行,直到出現值

+----+--------+------------+ 
| ID | Group | Breakpoint | 
+----+--------+------------+ 
| 1 | 1  | A   | 
| 2 | 1  | A   | 
| 3 | 1  | B   | 
| 4 | 1  | A   | 
| 5 | 2  | A   | 
| 6 | 2  | A   | 
| 7 | 2  | A   | 
| 8 | 3  | A   | 
| 9 | 3  | B   | 
+----+--------+------------+ 

這將是我的結果。

+----+--------+------------+ 
| ID | Group | Breakpoint | 
+----+--------+------------+ 
| 1 | 1  | A   | 
| 2 | 1  | A   | 
| 5 | 2  | A   | 
| 6 | 2  | A   | 
| 7 | 2  | A   | 
| 8 | 3  | A   | 
+----+--------+------------+ 

注意,當有一組內兩個AB斷點值,我想有行,直到順序第一A值。如果像group 2這樣的組中只有A的值,我想擁有組中的所有項目。

+0

你的PRIMARY KEY是什麼? – Strawberry

+0

對不起,這是一個虛擬表結果,我在上面的例子中添加了一個唯一的鍵! – ddinchev

+0

也許如果我們從頭開始.... – Strawberry

回答

1

這是一個簡單的解決方案,不使用子查詢或GROUP BY邏輯。

SELECT t1.ID, t1.Group, t1.Breakpoint 
FROM MyTable AS t1 
LEFT OUTER JOIN MyTable AS t2 
    ON t1.ID >= t2.ID AND t1.`Group` = t2.`Group` AND t2.Breakpoint = 'B' 
WHERE t2.ID IS NULL 

對於每一行t1,試圖找到與「B」的另一行t2,在同一組,與先前的ID。如果沒有找到,則OUTER JOIN保證t2.ID爲NULL。只有等到理想的斷點後,情況纔會如此。

0

SQL表格代表無序集合。因此,在特定的行之前沒有「之前」或「之後」。

讓我假設你有一些列指定了排序。我會叫它id。然後,你可以做你想做的有:

select t.* 
from t 
where t.id < (select min(t2.id) from t t2 where t2.group = t.group and t2.breakpoint = 'B'); 

要得到所有行的時候,如果沒有'B'

select t.* 
from t 
where t.id < (select coalesce(min(t2.id), t.id + 1) from t t2 where t2.group = t.group and t2.breakpoint = 'B'); 
+0

當不存在具有'breakpoint ='B''的行時,看起來像OP想要返回所有行。我認爲這個查詢排除了這些行。 (請參閱OP示例數據中的group = 2行,以及期望的輸出。) – spencer7593

1

從你上面的例子,你是不是真的分組結果。你只需要顯示的記錄,其中斷點答:

Select * From Table 
Where Breakpint ='A' 
+1

請注意,此查詢將返回從OP示例輸出中排除的行id = 4。 – spencer7593

0

您可以使用NOT EXISTS

select * 
from your_table t1 
where not exists (
    select 1 
    from your_table t2 
    where t1.group = t2.group and t2.id <= t1.id and t2.breakpoint = 'B' 
) 

ALL可以工作,以及如果你從來沒有NULLid

select * 
from your_table t1 
where t1.id < ALL(
    select t2.id 
    from your_table t2 
    where t1.group = t2.group and t2.breakpoint = 'B' 
) 
0

假設我們按ID列排序,我們可以這樣做:

SELECT d.* 
    FROM mytable d 
    LEFT 
    JOIN (SELECT bp.group 
       , MIN(bp.id) AS bp_id 
      FROM mytable bp 
      WHERE bp.breakpoint = 'B' 
      GROUP BY bp.group 
     ) b 
    ON b.group = d.group 
    WHERE b.bp_id > d.id OR b.bp_id IS NULL 
    ORDER BY d.group, d.id 

這是考慮到情況下,有沒有breakpoint='B'行對於給定的group,並返回所有的行爲group

請注意,內聯視圖bbreakpoint='B'行獲得的最低id值爲每個group。我們可以將外部聯接添加到原始表(匹配group),然後在WHERE子句中進行條件測試,以排除每個組的第一個breakpoint='B'後面的行。