Pobranie danych SQL

0

Mam tabelę:

id month year
1 10 2011
2 11 2011
3 12 2011
4 1 2012
5 2 2012
6 3 2012

chcę napisać zapytanie w którym będę mógł pobrać id od jakiegoś miesiąca i roku do jakiegoś miesiąca i roku i tak kiedy mam zapytanie:
select * from Table1 where (month >= 10 AND year = 2011) and (month <= 11 AND year = 2011) to jest ok pobiera prawidłowe dane ale jak dam:
select * from Table1 where (month >= 10 AND year = 2011) and (month <= 2 AND year = 2012) nic nie zwraca. Jak w jednym zapytaniu rozwiązać ten problem.

0
Janek2324 napisał(a):

(month >= 10 AND year = 2011) and (month <= 2 AND year = 2012)

Rzadko kiedy zdarza się, żeby jedna wartość była równocześnie równa 2011 i 2012, a żeby inna jeszcze była równocześnie większa lub równa 10 i mniejsza lub równa 2. ;)

0

Może inaczej jak w jednym zapytaniu pobrać id dla miesiąca z jednego roku lub dla miesięcy z roku 2011 i 2012

0
Janek2324 napisał(a):

Może inaczej jak w jednym zapytaniu pobrać id dla miesiąca z jednego roku lub dla miesięcy z roku 2011 i 2012

 select id from Table1 where year = 2011 and year = 2012

odpowiadając na pytanie główne wyświetlanie danych z jakiegoś zakresu to zastosuj BETWEEN w zapytaniu

0

Coś mi się zdaje, że nie o to koledze chodziło ;)
Tak czy inaczej, nie po ludzie wymyślili typ DATE, żeby takie rzeczy ręcznie robić. Może by kolumny month i year upchać w jedną? (Prawdopodobnie same korzyści z tego wynikną w dłuższym czasie).
A jak już się będziesz upierał przy swoim to zapytanie będzie bardziej skomplikowane, bo co jeśli podasz np zakres z dwóch lat? Dla twojego wycinka danych i tak powinieneś użyć warunku OR lub AND w zależności od tego czy rok startowy będzie taki sam jak końcowy,
np. forma:

SELECT *
FROM Table_1
WHERE (m >= 11 and r >= 2011)
	or (m <= 2 and r <= 2012)

Pobierze rekordy jak chcesz, ale nie zadziała już dla 11-2011 i 12-2012 bo zwróci również 10-2011 (pasuje do drugiego warunku), więc musisz stosować IF'a.
Przypadek, kiedy rok_startowy będzie się różnił o więcej niż 1 w porównaniu do rok_końca będziesz jeszcze bardziej rozbudowany.

0

@Xiuthechutli podejrzewam, że typ DATE nie pozwoli na wprowadzenie daty w formie miesiąc- rok, owszem może zrobić to w jednej kolumnie ale jako typ np. varchar, tylko wtedy efekt będzie gorszy niż teraz, bo teraz ma miesiące i lata jako number i może w jakiś sposób deklarować zakresy

0

Owszem jawnie np. '2010-10' nie konwertuje się na DATE, ale np.

SELECT CAST(CAST('2013' AS nvarchar(4))+'-'+CAST('2' AS nvarchar(2))+'-'+CAST('1' AS nvarchar(2)) AS DATE)

Mimo, że wygląda paskudnie i ogólnie nie polecam to po wstawieniu wartości pod 2013 i 2 zadziała prawidłowo.

0
Xiuthechutli napisał(a):

Coś mi się zdaje, że nie o to koledze chodziło ;)
Tak czy inaczej, nie po ludzie wymyślili typ DATE, żeby takie rzeczy ręcznie robić. Może by kolumny month i year upchać w jedną? (Prawdopodobnie same korzyści z tego wynikną w dłuższym czasie).
A jak już się będziesz upierał przy swoim to zapytanie będzie bardziej skomplikowane, bo co jeśli podasz np zakres z dwóch lat? Dla twojego wycinka danych i tak powinieneś użyć warunku OR lub AND w zależności od tego czy rok startowy będzie taki sam jak końcowy,
np. forma:

SELECT *
FROM Table_1
WHERE (m >= 11 and r >= 2011)
	or (m <= 2 and r <= 2012)

Pobierze rekordy jak chcesz, ale nie zadziała już dla 11-2011 i 12-2012 bo zwróci również 10-2011 (pasuje do drugiego warunku), więc musisz stosować IF'a.
Przypadek, kiedy rok_startowy będzie się różnił o więcej niż 1 w porównaniu do rok_końca będziesz jeszcze bardziej rozbudowany.

Prawie dobrze, ale co z 11/2013?

Lepiej - dla 11/2011..02/2012:

SELECT *
FROM Table_1
WHERE (m >= 11 AND r = 2011)
    OR (m <= 2 AND r = 2012)

dla 11/2011..02/2013 (z całym rokiem pośrodku, bardziej uniwersalne):

SELECT *
FROM Table_1
WHERE (m >= 11 AND r = 2011)
    OR (r > 2011 and r < 2013)
    OR (m <= 2 AND r = 2013)

czyli ogólnie

SELECT *
FROM Table_1
WHERE (m >= {month-1} AND r = {year-1})
    OR (r >  {year-1} and r <  {year-2})
    OR (m <= {month-2} AND r =  {year-2})
0

@vpiotr Twoje rozwiązanie z hardkodowaniem wartości -1, -2 niestety ma mnóstwo przypadków w których również nie zadziała prawidłowo, znów co gdy dojdzie do tabeli rok 2014, a ktoś będzie potrzebował informacji od 2010 do 2014?

Bez zmiany architektury tj upierając się przy int'ach do zapisu miesiąca i roku Cast wygląda tragicznie, jest wolny, ale działa.

DECLARE @od DATE = '2011-11-01'
DECLARE @do DATE = '2013-02-01'
 
SELECT * FROM Table_1 T
WHERE CAST(CAST(T.year AS nvarchar(4))+'-'+CAST(T.month AS nvarchar(2))+'-'+CAST('1' AS nvarchar(2)) AS DATE) between @od and @do
1
Xiuthechutli napisał(a):

@vpiotr Twoje rozwiązanie z hardkodowaniem wartości -1, -2 niestety ma mnóstwo przypadków w których również nie zadziała prawidłowo, znów co gdy dojdzie do tabeli rok 2014, a ktoś będzie potrzebował informacji od 2010 do 2014?

W kodzie:

SELECT *
FROM Table_1
WHERE (m >= {month-1} AND r = {year-1})
    OR (r >  {year-1} AND r <  {year-2})
    OR (m <= {month-2} AND r =  {year-2})

nie ma żadnych hardcodów

{month-1} - zamień na miesiąc z daty nr 1
{year-1} - zamień na rok z daty nr 1

{month-2} - zamień na miesiąc z daty nr 2
{year-2} - zamień na rok z daty nr 2

Co oczywiście oznacza, że rozwiązanie zadziała także z nowymi datami.

Co do CAST to może wyglądać jak chce, ale czy wykorzysta indeks?

1 użytkowników online, w tym zalogowanych: 0, gości: 1