2013-07-02 50 views
-2

我有這樣的一個表中的字段:MySQL的:一個奇怪的查詢:選擇具有多條記錄

---------- 
id | name | tel | email 
---------- 
1 john 0241 [email protected] 
2   0534 [email protected] 
3   435  [email protected] 
4 geo  43435 [email protected] 
5   2347 [email protected] 
6   678  [email protected] 

我要讓這樣的查詢:

SELECT tel, email FROM table WHERE name='geo' 

和輸出是這樣的:

---------- 
    tel | email 

---------- 

43435 [email protected] 
2347 [email protected] 
678  [email protected] 

非常感謝你提前

+6

應付爲什麼它應該包括這些記錄時,他們沒有'name =「緣」? – Barmar

+0

你好,社區在這裏是嚴格的。你必須提出一個適當的問題。順便說一句。你只有一個名字爲'geo'的記錄,所以這個查詢會輸出'43435 re @ eae' –

+1

這是什麼表中缺少名字?這是你的真實表格數據嗎?如果是這樣,查詢將只返回第4行。 –

回答

1
SELECT tel, name FROM 
(SELECT id FROM table WHERE name = 'geo') a 
LEFT JOIN table b ON 
b.id = a.id 
WHERE b.id >= a.id AND b.id < (SELECT id from table WHERE name > '' 
ORDER BY ID ASC 
LIMIT 1) c 
+1

這將讓你在匹配記錄'地理'後存儲的所有記錄 –

+1

我不認爲這很簡單,他可能只希望他們到有真名的下一行。 – Barmar

+1

'WOOPS'。這將返回id大於包含'geo'的行的每一行,即其表中的其餘部分。 – RiggsFolly

2
SELECT tel, email 
FROM table1 
JOIN (SELECT MAX(startid) startid, 
      IFNULL(MAX(endid), (SELECT MAX(id) FROM table1)) endid 
    FROM (SELECT id startid, NULL endid FROM table1 WHERE name = 'geo' 
      UNION 
      SELECT NULL, MIN(id)-1 FROM table1 
      WHERE name != '' 
      AND id > (SELECT id FROM table1 WHERE name = 'geo')) x) y 
ON id BETWEEN startid AND endid 

SQLFIDDLE

+0

非常喜歡這個解決方案,因爲它避免了我的解決方案依賴的用戶變量(這些不可讀,並且有太多可能需要維護select的人不理解它們)。有一個戲劇,並使用相同的邏輯,但主要使用加入我已簡化了它觸摸我認爲 – Kickstart

+1

@Kickstart是的,我沒有瘋狂的所有嵌套和重複'geo'。我認爲用LEFT JOIN會有更好的方法,但是太累了,無法解決。 – Barmar

+0

這對我來說是最好的解決方案。先生非常感謝您。 – tuxman

0

假設ID正在增加,但沒有名稱的下一個條目屬於同一個,這將是最簡單的更新您的表。

方法如下:

Test data: 
/* 
drop table yourTable; 
CREATE TABLE yourTable 
    (`id` int, `name` varchar(40), `tel` int, `email` varchar(20)) 
; 

INSERT INTO yourTable 
    (`id`, `name`, `tel`, `email`) 
VALUES 
    (1, 'john', 0241, '[email protected]'), 
    (2, NULL, 0534, '[email protected]'), 
    (3, NULL, 435, '[email protected]'), 
    (4, 'geo', 43435, '[email protected]'), 
    (5, NULL, 2347, '[email protected]'), 
    (6, NULL, 678, '[email protected]'), 
    (7, 'anything', 789, 'whatever') 
; 
#*/ 


UPDATE yourTable yt1 INNER JOIN (
SELECT 
yt.*, 
COALESCE(name, @prev) AS newName, 
CASE WHEN name IS NOT NULL THEN @prev:=name END 
FROM 
yourTable yt 
, (SELECT @prev:=NULL) v 
ORDER BY id 
) yt2 ON yt1.id = yt2.id 
SET yt1.name = yt2.newName; 

SELECT * FROM yourTable; 

結果:

id name  tel email 
1 john  241 [email protected] 
2 john  534 [email protected] 
3 john  435 [email protected] 
4 geo   43435 [email protected] 
5 geo   2347 [email protected] 
6 geo   678 [email protected] 
7 anything 789 whatever 

然後將查詢應該可以正常工作。

0
SELECT i.id, i.tel, i.email 
FROM 
    tableX AS t 
    JOIN 
    tableX AS i 
     ON i.id >= t.id 
     AND i.id < COALESCE(
      (SELECT n.id 
      FROM tableX AS n 
      WHERE n.id > t.id 
       AND n.name <> '' 
      ORDER BY n.id ASC 
       LIMIT 1 
     ), 2147483647) 
WHERE 
    t.name = 'geo' ; 

SQL-Fiddle-1(日Thnx @Barmar)

1

使用用戶變量測試: -

SELECT tel, email 
FROM 
(
    SELECT Sub1.id, Sub1.name, Sub1.tel, Sub1.email, @name:=IF(name IS NULL, @name, name) AS aName 
    FROM (SELECT * FROM geoname ORDER BY id) Sub1 
    CROSS JOIN (SELECT @name:="") Sub2 
) Sub3 
WHERE aName = 'geo' 

由於Barmar強調,如果名字字段爲空時,在空它,而不是這僅適用於''。如果它需要應付空白以及NULL: -

SELECT tel, email 
FROM 
(
    SELECT Sub1.id, Sub1.name, Sub1.tel, Sub1.email, @name:=IF(name IS NULL OR name = "", @name, name) AS aName 
    FROM (SELECT * FROM Table1 ORDER BY id) Sub1 
    CROSS JOIN (SELECT @name:="") Sub2 
) Sub3 
WHERE aName = 'geo' 

有一點戲劇。挺喜歡通​​過Barmar的解決方案,但有一個發揮,如果我能簡化並消除了幾個子查詢的: -

SELECT a.* 
FROM geoname a 
INNER JOIN 
(
    SELECT a.id AS MinId, IFNULL(MIN(b.id), MAX(c.id)) AS MaxId 
    FROM geoname a 
    LEFT OUTER JOIN geoname b 
    ON a.id < b.id AND b.name IS NOT NULL 
    CROSS JOIN geoname c 
    WHERE a.name = 'geo' 
    GROUP BY a.id 
) Sub1 
ON a.id BETWEEN Sub1.MinId AND Sub1.MaxId 

稍微快似乎和有一個簡單的解釋。

或者用空格以及NULLS

SELECT a.* 
FROM geoname a 
INNER JOIN 
(
    SELECT a.id AS MinId, IFNULL(MIN(b.id), MAX(c.id)) AS MaxId 
    FROM geoname a 
    LEFT OUTER JOIN geoname b 
    ON a.id < b.id AND b.name IS NOT NULL OR b.name = '' 
    CROSS JOIN geoname c 
    WHERE a.name = 'geo' 
    GROUP BY a.id 
) Sub1 
ON a.id BETWEEN Sub1.MinId AND Sub1.MaxId 
+1

這隻返回1行,請參閱http://www.sqlfiddle.com/#!2/8e6758/7 – Barmar

+0

在SQL小提琴中,名稱字段爲空,而這是假設NULL字段。輕鬆修改,以處理空白。 – Kickstart

+0

你是對的,http://www.sqlfiddle.com/#!2/3a526/1 – Barmar