2012-04-24 6 views
6

Mam nietypowy tabel SQL (nie mój), który ma następujące pola (między innymi): last_name, primary_name, secondary_name, oznaczające małżeństwa. Przyjmuje się, że ostatnie nazwisko jest udostępniane (niezbyt nowoczesne, wiem), a jeśli nie jest to para, to albo primary_name lub secondary_name może mieć wartość NULL. (Tabela ma również kilka duplikatów.)Czy mogę utworzyć zapytanie SQL, wykonując dwa dopasowania w każdym wierszu?

Co chcę zrobić, to uzyskać listę wszystkich nazw ("pierwszy raz") w bazie danych, alfabetycznie w zwykły sposób. Teraz robię dwie wejściówki za pośrednictwem bazy danych za pomocą PHP i PDO:

$qstr = "SELECT DISTINCT primary_name, last_name 
      FROM members 
      WHERE primary_name IS NOT null 
      ORDER BY last_name, primary_name"; 
$sth = $dbh->prepare($qstr); 
$sth->execute(); 
// output the results 

$qstr = "SELECT DISTINCT secondary_name, last_name 
      FROM members 
      WHERE secondary_name IS NOT null 
      ORDER BY last_name, secondary_name"; 
$sth = $dbh->prepare($qstr); 
$sth->execute(); 
// output the new results 

Ale efekt końcowy nie jest alfabetyczna, ponieważ drugi przebieg rozpoczyna się od nowa.

Jak mogę uzyskać wszystkie nazwiska na raz, alfabetycznie całkowicie? Czy jest jakiś sposób, aby to zrobić w SQL, czy muszę zbudować dwie tablice i ponownie je alfabetować w PHP?

EDIT Baza wygląda mniej więcej tak:

last_name primary_name secondary_name 
---------------------------------------- 
Abrams  Joe   Susan 
Miller  Sam   Abby 

pożądany wynik byłby coś takiego:

["Joe Abrams","Susan Abrams","Abby Miller","Sam Miller"] 

Zamiast tego, jeśli pierwsze przejście pobiera wszystkie mężów i tym Drugie podanie wszystkich żon, otrzymuję coś takiego:

["Joe Abrams","Sam Miller","Susan Abrams","Abby Miller"] 
+0

Czy możesz podać przykład wyjścia, które chcesz wyświetlić (używając 4 lub 5 różnych kombinacji nazw)? –

Odpowiedz

2

Alternatywą jest użycie UNION ...

SELECT 
    * 
FROM 
(
    SELECT primary_name AS pri_sec_name, last_name 
    FROM members 
    WHERE primary_name IS NOT null 

    UNION 

    SELECT secondary_name AS pri_sec_name, last_name 
    FROM members 
    WHERE secondary_name IS NOT null 
) 
    AS data 
ORDER BY 
    last_name, pri_sec_name 

UWAGA:UNION(w przeciwieństwie do UNION ALL) spowoduje zduplikowanie wyników.

Innym jest dołączenie do tabeli mapowania.

SELECT 
    members.last_name, 
    CASE WHEN map.mode = 1 THEN members.primary_name ELSE members.secondary_name END AS pri_sec_name 
FROM 
    members 
INNER JOIN 
    (SELECT 1 as mode UNION ALL SELECT 2 as mode) AS map 
    ON (map.mode = 1 AND members.primary_name IS NOT NULL) 
    OR (map.mode = 2 AND members.secondary_name IS NOT NULL) 
ORDER BY 
    1, 
    2 
+0

UNION to jedna z tych rzeczy, o których zapomniałem dawno temu z powodu braku użycia. To wydaje się działać, ale czy możesz mi wyjaśnić część zapytania "Dane AS"? – Blazemonger

+0

Nieważne, błąd SQL właśnie mi to wyjaśnił. – Blazemonger

+0

@Blazemonger - Chodzi tylko o zawinięcie wszystkiego w pod-zapytanie, a następnie nadanie temu pod-zapytaniu nazwy. Jest to często znane jako * widok w wierszu *, ponieważ traktujesz swoje pod-zapytanie jako widok. 'WYBIERZ * Z () AS MyViewName' – MatBailie

7

Jeśli dobrze rozumiem, myślę, że szukasz czegoś takiego:

select distinct coalesce(primary_name, secondary_name) as pri_sec_name, 
    last_name 
from members 
where coalesce(primary_name, secondary_name) is not null 
order by last_name, 
    coalesce(primary_name, secondary_name) 

aktualizacji

Brzmi jak w niektórych przypadkach masz jeden wiersz dla LAST_NAME, gdzie zarówno PRIMARY_NAME i nazwa secondary_name są wypełnione. Poniższe zapytanie powinno dać wyjście chcesz (przepraszam, nie COALESCE ten czas):

select last_name, pri_sec_name 
from (
    select primary_name as pri_sec_name, last_name from members where primary_name is not null 
    union all 
    select secondary_name as pri_sec_name, last_name from members where secondary_name is not null 
) a 
order by last_name, pri_sec_name 
+1

+1 do odszyfrowania tego. –

+0

+1 Kocham Coalesce! –

+0

Po raz pierwszy usłyszałem o "koalescencji". Jaki będzie wynik tego SQL? Wydaje mi się, że wciąż otrzymuję jeden wiersz wyników dla każdego wiersza tabeli, kiedy (przez większość czasu) potrzebuję dwóch wierszy wyników dla każdego wiersza tabeli. – Blazemonger

2

myślę, że trzeba:

SELECT primary_name AS name 
    , last_name 
    FROM members 
    WHERE primary_name IS NOT NULL 
UNION 
SELECT secondary_name 
    , last_name 
    FROM members 
    WHERE secondary_name IS NOT NULL 
ORDER BY last_name, name 

Innym przepisać korzysta UNION ALL:

SELECT COALESCE(primary_name, secondary_name) AS name 
    , last_name 
    FROM members 
UNION ALL 
SELECT secondary_name 
    , last_name 
    FROM members 
    WHERE primary_name IS NOT NULL 
    AND secondary_name IS NOT NULL 
ORDER BY last_name, name 

The 2nd wersja może być szybciej, ale może pokazać zduplikowanych wyników.Jeśli więcej przykład, masz te wiersze, jeden Joe Jackson żonatych do Susan i jeden żonaty z Lea:

last_name primary_name secondary_name 
---------------------------------------- 
Jackson Joe   Susan 
Jackson Joe   Lea 

Pierwszy qould zapytanie pokaz:

name last_name 
----------------- 
Joe Jackson 
Lea Jackson 
Susan Jackson 

natomiast druga musiałaby „duplikaty”:

name last_name 
----------------- 
Joe Jackson 
Joe Jackson 
Lea Jackson 
Susan Jackson 

Co jest bardziej właściwe, zależy od specyfikacji.

Powiązane problemy