2013-04-23 15 views
6

mam tej tabeli o nazwie people z dwiema datami na MySQL:Wybierz sekwencję pomiędzy dwoma numerami na MySQL

| Name | start_date | end_date | 
| John | 2007-03-01 | 2009-10-12 | 
| Mike | 2001-06-06 | 2010-12-01 | 

Chcę utworzyć widok, który pozwala mi szukać po roku działalności, będąc roku aktywność dowolny rok pomiędzy start_date i end_date. Tak, chciałbym, aby uzyskać pole z sekwencją lat tak:

| Name | activity_years         | 
| John | 2007,2008,2009         | 
| Mike | 2001,2002,2003,2004,2005,2006,2007,2008,2009,2010 | 

Próbowałem kilka podejść, ale nie mogę dostać. Ponieważ chcę utworzyć widok, muszę zrobić to wszystko wewnątrz instrukcji SELECT i to sprawia mi ból głowy.

+0

Nic że warty wzmianki. Próbowałem pętli wewnątrz SELECT i stworzyłem procedurę, która stworzyła sekwencję, ale nie udało mi się jej uruchomić, prawdopodobnie dlatego, że czegoś mi brakowało. –

Odpowiedz

5

Coś jak to powinno zrobić: -

SELECT a.Name, GROUP_CONCAT(YEAR(DATE_ADD(a.start_date, INTERVAL b.aNum YEAR))) AS activity_years 
FROM person a 
CROSS JOIN (SELECT a.i + b.i * 10 AS aNum FROM integers a, integers b) b 
WHERE YEAR(DATE_ADD(a.start_date, INTERVAL b.aNum YEAR)) <= YEAR(a.end_date) 
GROUP BY a.Name 

Opiera się na stole liczb całkowitych z kolumną o nazwie I, z wartościami od 0 do 9. To łączy ten sam przeciwko sobie, aby uzyskać zakres numerów od 0 do 99, więc radzi sobie z zakresami dat, które są daleko od siebie.

Usuwanie podselekcji wykorzystać go w widoku

SELECT p.Name, GROUP_CONCAT(YEAR(DATE_ADD(p.start_date, INTERVAL (a.i + b.i * 10) YEAR))) AS activity_years 
FROM person p 
CROSS JOIN integers a 
CROSS JOIN integers b 
WHERE YEAR(DATE_ADD(p.start_date, INTERVAL (a.i + b.i * 10) YEAR)) <= YEAR(p.end_date) 
GROUP BY p.Name 
+0

Jeśli OP stwierdzi, że jest dopuszczalne utworzenie nowej stałej tabeli pomocy, lepiej byłoby po prostu nazwać ją Years i przechowywać wszystkie możliwe lata w niej (na przykład 1980-2050) i po prostu JOIN na tym stole, aby uzyskać dane? –

+0

Punkt kulminacyjny i prawdopodobnie prawda. Zależy od zakresów dat, częstotliwości ich użycia itp. Na przykład, jeśli zakres dat był dla daty urodzenia i daty śmierci przodków sprzed tysiąca lat, może być nieco mniej elastyczny. Także jeśli ma zostać rozszerzony, aby dać wszystkie miesiące i lata w zakresie, to jest to łatwe do zrobienia. – Kickstart

+0

Edytowane, aby usunąć potrzebę podselekcji – Kickstart

4

SQLFiddle demo

select name, 
     group_concat(tYears.row ORDER BY tYears.row) 
    from people 

join 

(
SELECT @row := @row + 1 as row FROM 
(select 0 union all select 1 union all select 3 union all select 4 union all 
    select 5 union all select 6 union all select 6 union all select 7) t, 
(select 0 union all select 1 union all select 3 union all select 4 union all 
    select 5 union all select 6 union all select 6 union all select 7) t2, 
(select 0 union all select 1 union all select 3 union all select 4 union all 
    select 5 union all select 6 union all select 6 union all select 7) t3, 

(SELECT @row:=1900) t21 
) tYears 

on tYears.row between year(start_date) and year(end_date) 
group by name 
+0

Nie w pełni to rozumiem, ale i tak nie mogę go uruchomić. Wydaje się, że działa poprawnie na zwykłym SELECT, ale nie mogę umieścić tego SELECT w VIEW. Otrzymuję ten błąd: 'Błąd 1349: View SELECT zawiera podkwerendę w klauzuli FROM klauzuli SQL' –

+2

Jest to dość proste. Jest to krzyż łączący wyniki kilku selekcji razem, aby uzyskać dużą liczbę wyników (każdy z selekcji przywraca 8 wierszy, więc zwrócono 512 wierszy) i łączenie tego z wyborem dla zmiennej początkowej (np. @row) ustawiona na 1900. Następnie przywraca tę zmienną raz dla każdego wiersza, dodając po 1 za każdym razem. Stąd zakres od 1901 do 2413. Następnie odrzuca wszelkie wystąpienia tej zmiennej, która nie jest między rokiem danych początkowych a datą końcową, a następnie wykorzystuje GROUP_CONCAT, aby sprowadzić pozostałe lata z powrotem do jednego pola. – Kickstart

+0

Dziękuję za wyjaśnienie, jednak to nadal nie zadziała, ponieważ ograniczenie podzapytań na widokach. –

Powiązane problemy